Given this example:
Pivoted Table
And the desired output is the following:
Desired Result
So my question is. I'm running a proprietary server which I cannot mention here and this server does not support UNPIVOT operator. I have tried so far the following:
SELECT week,
day,
username,
CASE
WHEN main_cat_1 = "cars" THEN "cars"
WHEN main_cat_2 = "vans" THEN "vans"
ELSE null END AS main_cat,
CASE
WHEN sub_cat_1.1 = "dirty" THEN "dirty"
WHEN sub_cat_1.2 = "stalled" THEN "stalled"
ELSE null END AS sub_cat
FROM table1
The issue with this approach is that because of short-circuit evaluation after the first TRUE valueit does not seem to work properly and does not return the expected values.
SELECT week,
day,
username,
main_cat_1 as category,
sub_cat_1.1 as subcategory
FROM table1
UNION
SELECT week,
day,
username,
main_cat_1,
sub_cat_1.2
FROM table1
UNION
...etc.
Related
SELECT DISTINCT
Member_ID,
CASE
WHEN a.ASTHMA_MBR = 1 THEN 'ASTHMA'
WHEN a.COPD_MBR = 1 THEN 'COPD'
WHEN a.HYPERTENSION_MBR = 1 THEN 'HYPERTENSION'
END AS DX_FLAG
So a member may have more than one, but my statement is only returning one of them.
I'm using Teradata and trying to convert multiple columns of boolean data into one column. The statement is only returning one condition when members may have 2 or more. I tried using Select instead of Select Distinct and it made no difference.
This is a kind of UNPIVOT:
with base_data as
( -- select the columns you want to unpivot
select
member_id
,date_col
-- the aliases will be the final column value
,ASTHMA_MBR AS ASTHMA
,COPD_MBR AS COPD
,HYPERTENSION_MBR AS HYPERTENSION
from your_table
)
,unpvt as
(
select member_id, date_col, x, DX_FLAG
from base_data
-- now unpivot those columns into rows
UNPIVOT(x FOR DX_FLAG IN (ASTHMA, COPD, HYPERTENSION)
) dt
)
select member_id, DX_FLAG, date_col
from unpvt
-- only show rows where the condition is true
where x = 1
The following is a simplified example of a problem I'm running into. Assume I have a query "SomeQuery" (SELECT... FROM... WHERE...) that gives an output that looks like this:
Status
MyDate
A
6/14/2021
A
6/12/2021
B
6/10/2021
A
6/8/2021
B
6/6/2021
A
6/4/2021
I need to get the earliest status A date that is greater than the maximum status B date. In this case 6/12/2021.
I have a query that looks like this:
SELECT
MIN(MyDate) AS DateNeeded
FROM
SomeQuery
WHERE
Status = 'A'
AND MyDate > (
SELECT
MAX(MyDate) AS MaxDateB
FROM
SomeQuery
WHERE
Status = 'B'
)
This works, but I would like to avoid running the subquery twice. I tried assigning an alias to the first instance of the subquery, and then using that alias in place of the second instance, but this results in an "Invalid object name" error.
Any help would be appreciated. Thanks.
but to avoid hitting table twice you could use window function:
select top(1) Mydate from
(
select *, max(case when Status = 'B' then Mydate end) over () MaxBDate from data
) t
where status = 'A'
and MyDate > MaxBDate
order by Mydate
db<>fiddle here
I'm not sure I understand what you're after exactly, but it is possible to do something like this:
;WITH cte (MaxMyDate) as
(
SELECT
MAX(MyDate) AS MaxDateB
FROM
SomeQuery
WHERE
Status = 'B'
)
SELECT
MIN(MyDate) AS DateNeeded
FROM
SomeQuery
WHERE
Status = 'A'
AND MyDate > (SELECT MaxMyDate from cte)
Some may find this a bit easier to read, since some of the complexity is moved to a cte.
Here is the query I am using to generate last date of each week. However the filter does not seem to take affect. and the starting date I get is "2016-01-03".
SELECT TO_DATE(last_day(DATEADD(DAY, SEQ4()*7, '2016-01-01 00:00:00'), 'week')) AS WEEK_LAST_DATE
FROM TABLE(GENERATOR(ROWCOUNT=>1000))
WHERE WEEK_LAST_DATE > '2016-09-07';
The following works though:
SELECT * from (
SELECT TO_DATE(last_day(DATEADD(DAY, SEQ4()*7, '2016-01-01 00:00:00'), 'week')) AS WEEK_LAST_DATE
FROM TABLE(GENERATOR(ROWCOUNT=>1000))
) as A
WHERE A.WEEK_LAST_DATE > '2016-09-07';
Why does the first query not work?
In general in SQL, you can't refer to an expression defined in the select clause in the same scope - left apart the order by clause. Typically, this raises a syntax error:
select t.*, 'abc' as newcol
from mytable t
where newcol = 'abc'
newcol is defined in the select clause, hence not available in the where clause. This is typically worked around by computing the value in an inner scope, then using it for filtering in an outer scope: subqueries, lateral joins, and common table expressions are the most common approaches. So:
select *
from (
select t.*, 'abc' as newcol
from mytable t
) t
where newcol = 'abc'
I am surprised that your first query even compiles; it may be some Snowflake-specific thing. But the second query is indeed the right way to do what you want:
Im making a betting system app. I need to count the points of a user based on his bets, knowing that some of the bets can be 'combined', which makes the calcul a bit more complex than a simple addition.
So if i have 3 bets: {points: 3, combined: false}, {points: 5, combined: true}, {points: 10, combined: true}, there are two bets combined here, so the total points should be 3 + (5 * 2) + (10 * 2). Reality is a bit more complex since the points are not directly in the bet object but in the match it refers to
Here is a part of my query. As you can see, i first check if the bet is right based on the match result, in that case if the bet is combined I multiply it by the value of combinedLength, else i'll just sum the value of that bet. I tried to replicate the COUNTIF inside the CASE, which gaves me an error like 'cannot aggregation inside aggregation'.
SELECT
JSON_EXTRACT_SCALAR(data, '$.userId') AS userId,
COUNTIF(JSON_EXTRACT_SCALAR(data, '$.combined') = 'true') AS combinedLength,
SUM (
(
CASE WHEN JSON_EXTRACT_SCALAR(data, '$.value') = match.result
THEN IF(JSON_EXTRACT_SCALAR(data, '$.combined') = "true", match.odd * combinedLength, match.odd)
ELSE 0
END
)
) AS totalScore,
FROM data.user_bets_raw_latest
INNER JOIN matchLines ON matchLines.match.matchId = JSON_EXTRACT(data, '$.fixtureId')
GROUP BY userId
I've been looking for days... thanks so much for the help !
If I follow you correctly, then you need to count the total number of combined bets per user in a subquery, using a window function. Then, you can use this information while aggregating.
Consider:
select
user_id,
sum(case when combined = 'true' then odd * cnt_combined else odd end) total_score
from (
select
u.*,
m.match.odd,
countif(b.combined = 'true') over(partition by userid) as cnt_combined,
from (
select
json_extract_scalar(data, '$.userid') userid,
json_extract_scalar(data, '$.combined') combined,
json_extract_scalar(data, '$.value') value,
json_extract_scalar(data, '$.fixtureid') fixtureid
from data.user_bets_raw_latest
) b
left join matchlines m
on m.match.matchid = b.fixtureid
and m.match.result = b.value
) t
group by userid
I find that it is simpler to use a left join and put the condition on the match result in there.
I moved the json extractions to a subquery to reduce the length of the query.
I have a query that has EXISTS query, which has PRCS_STE_CD column.
QUERY
SELECT
PRCS_SNO
, YEAR
, SUBSC_CANC_YN
FROM
TB_POT_ECD_PRCS_INFO INF
WHERE
INF.SUBSC_CANC_YN = 'N'
AND EXISTS (
SELECT 'X'
FROM TB_POT_ECD_PRCS_HIST HIS
WHERE PRCS_STE_CD = 'R01'
)
Idea is to show only ones that PRCS_STE_CD = 'R01'.
But the problem is that some have 'R01' and 'R02' for PRCS_STE_CD.
(In this case, where it has both R01 and R02, I do not want to show it on the list.)
Basiacally, I want to show one that only has R01 for PRCS_STE_CD.
Oh and PRCS_STE_CD CAN NOT have only R02. It must have R01 in order to have R02.
And again, when it has both R01, R02, it should not be selected on the list.
Can anyone help editing the query?
In your table how have you stored R02 for PRCS_STE_CD. I assume you have a different column to store R02. If so then you can try using the IN and the OR Operators as.
SELECT
PRCS_SNO, YEAR, SUBSC_CANC_YN
FROM TB_POT_ECD_PRCS_INFO INF
WHERE INF.SUBSC_CANC_YN = 'N'
AND 'X' IN (
SELECT 'X'
FROM TB_POT_ECD_PRCS_HIST HIS
WHERE PRCS_STE_CD = 'R01' OR Second_Column= 'R02'
)