In my use case, I need to do something like this,
INSERT INTO TABLE test
select
count(*) where recordedValue < 0,
count(*) where recordedValue > 0 and recordedValue < 10,
count(*) where recordedValue > 10 and recordedValue < 20
from sample
Is it possible to do like this?
INSERT INTO TABLE test
select count(col1), count(col2), count(col3) From (
select
CASE WHEN recordedValue < 0 THEN recordedValue END as col1,
CASE WHEN recordedValue > 0 AND recordedValue < 10 THEN recordedValue END as col2,
CASE WHEN recordedValue > 10 AND recordedValue < 20 THEN recordedValue END as col3
from sample ) a;
first check select statement;
Related
Let's say I have a table called temp which contains int attributes a and b:
create table temp (id int primary key, a int, b int);
insert into temp values(1, 1, 1);
insert into temp values(2, -1, 1);
insert into temp values(3, -1, -1);
I need to sort some SELECT results depending on which one WHERE condition succeeded. A primitive but not working example:
select *, priority from temp where (
case
when a > 0 and b > 0 then 1
when a > 0 or b > 0 then 2
else 0
end
as priority
) > 0 order by priority asc
It says something like "if a and b are both positive then this tuple will be one of the firstest. If at least one of the attributes is positive then this tuple comes after first ones. Else don't select the tuple"
So is it possible to save a CASE result to use it in ORDER? Or maybe there are workarounds without having to check the conditions twice in both WHERE and ORDER or making possibly expensive UNION?
Please explain what is wrong with this(if anything is)?
select *
from temp
order by case
when a > 0 and b > 0 then 1
when a > 0 or b > 0 then 2
else 0
end
Just use your case when then end logic in order by clause(without using "priority" alias).
Here is a demo
Then this should be ok for you:
select * --to select all
from temp --from your table
where (a > 0 or b > 0) --where a or b is bigger than 0 because this is the same as your case when then end example
order by case --I have used your logic for order by clause
when a > 0 and b > 0 then 1
when a > 0 or b > 0 then 2
else 0
end
Here is a second demo
And this is a third option suggested by OP:
select *
from temp
where (a > 0 or b > 0)
order by case
when a > 0 and b > 0 then 0
else 1
end
Here is a third demo
I have the following select statement in Redshift that will return rows with certain values if the condition inside is met. I want to transform this into a DQ check which will return 1 (True) if no rows ae returned or 0 if any row is returned, but I do not know where I should apply the case statement.
Here is the select statement:
select * from (select brand,calendar_dt, product,
count(account) count from revenue_base
where player_days = 0 and volume_loc >0 group by brand,calendar_dt, product)
where count > 1000 and calendar_dt >='2020-07-12'
and calendar_dt < '2020-07-13'
Can you please offer me some ideas for this?
You may try using exists logic here:
select
case when not exists (
select 1 from
(
select brand, calendar_dt, product, count(account) as count
from revenue_base
where player_days = 0 and volume_loc > 0
group by brand, calendar_dt, product
) t
where calendar_dt >= '2020-07-12' and calendar_dt < '2020-07-13' and
count > 1000
)
then 1 else 0 end as result;
First, Redshift supports booleans, so case is not needed. Second, do the filtering on the date before the aggregation. This is usually faster.
Then, you can filter by the count using a having clause, so no subquery is needed:
select not exists (select 1
from revenue_base
where player_days = 0 and volume_loc > 0 and
calendar_dt >= '2020-07-12' and calendar_dt < '2020-07-13'
group by brand, calendar_dt, product
having count(*) > 1000
) as result
Trying to get a selection of records where if COUNT ([WHO]) > 1 then select [WHO] where the [LIT] <> 0.
Example if [WHO] = '12082132' , '12082132' and [LIT] = 0, then ignore [WHO].
WHO LIT COUNT
3517015 7 1
3523687 0 1
12057744 0 2
12058316 7 1
12059820 7 1
12082132 2 2
12082132 5 1
12082132 1 3
12082132 14 1
12082132 0 1
I have tried grouping, case statements, but I think I am trying to get something that is not possible. Any help will do.
Expected results
WHO LIT COUNT
3517015 7 1
12058316 7 1
12059820 7 1
Trying to get a selection of records where if COUNT ([WHO]) > 1 then select [WHO] where the [LIT] <> 0.
Is this what you want?
select t.*
from (select t.*, count(*) over (partition by who) as cnt
from t
) t
where cnt > 1 and lit <> 0;
You can use not exists & use window function :
select t.*, count(*) over (partition by t.who) as cnt
from table t
where not exists (select 1
from table t1
where t1.who = t.who and t1.lit = 0
);
Simple NOT IN will work
SELECT * FROM #Table
WHERE [WHO] NOT IN (
SELECT DISTINCT [WHO]
FROM #Table
WHERE CASE WHEN [LIT] >= 1 THEN 0 ELSE 1 END = 1
)
This is an example, I hope it helps you,I think that it does what you want but its a little tricky, maybe can lead you to an answers at least if it's not
what you want.
drop table #testMr
drop table #checkTest
create table #testMr(who numeric, lit numeric, count_x numeric)
create table #checkTest(who numeric, lit numeric, count_x numeric,countWho numeric)
insert into #testMr values(3517015,7,1)
insert into #testMr values(3523687,0,1)
insert into #testMr values(12057744,0,1)
insert into #testMr values(12058316,7,1)
insert into #testMr values(12082132,1,3)
insert into #testMr values(12082132,14,1)
insert into #testMr values(12082132,7,1)
insert into #testMr values(12082132,0,1)
insert into #checkTest
select who,sum(lit) as [lit],sum(count_x) as [CountX],count(who) as [CountWho] from #testMr
where who in(select b.who from #testMr as b where b.lit<>0) group by who having count(who)>1
if(select count(*) from #checkTest)>0
begin
--there are some invalid values so we filter by the lit<>0 and remove the invalid ones.
select * from #testMr where lit<>0 and who not in(select b.who from #checkTest as b)
end
else
begin
--'All values are Ok and we filter by the count who.'
select who,sum(lit) as [lit],sum(count_x) as [CountX] from #testMr group by who having count(who)>1
end
Let's consider the following scenario.
CREATE TABLE Replicant (Name NVARCHAR(10),Gen INT);
INSERT INTO Replicant VALUES ('tymtam', 2), ('Roy', 6);
SELECT
CASE WHEN Gen < 10 THEN '<10' ELSE '>=10' END as 'Gen',
count(*) as 'Count'
FROM Replicant
GROUP BY CASE WHEN Gen < 10 THEN '<10' ELSE '>=10' END;
The result is a single row:
Gen Count
<10 2
Can I up-sophisticate the query so that I get a zero for the ELSE case?
Gen Count
<10 2
>=10 0
Update 2
My discriminator is 'is null'
SELECT CASE WHEN Gen IS NOT NULL THEN 'Known' ELSE 'Unknown' END as 'Gen', count(*) as 'Count' FROM Replicant
GROUP BY CASE WHEN Gen IS NOT NULL THEN 'Known' ELSE 'Unknown' END;
The result is
Gen Count
Known 2
and I yearn for
Gen Count
Known 2
Unknown 0
Update 1
My context is that I have pairs of queries (metrics) for different generations of replicants:
INSERT INTO [dbo].[Metrics] (...) SELECT
'Metric X for >=10' as 'Name',
COUNT(*) AS 'Count',
(80_char_expression) AS 'Sum',
(80_char_expression) AS 'Min',
(80_char_expression) AS 'Max',
0 AS 'StandardDeviation'
FROM Replicant
WHERE TimestampUtc > DATEADD(WEEK, -1, Current_Timestamp)
AND Gen >= 10
INSERT INTO [dbo].[Metrics] (...) SELECT
'Metric X for <10' as 'Name',
--7 lines repeated from the 1st query
AND Gen < 10
I would prefer to have a single select to insert two rows, even if there are no records.
You can try to use UNOIN ALL make a comparison table for your score then do outer join
Query 1:
SELECT t1.word,
COUNT(Name) 'Count'
FROM
(
SELECT '<10' word,9 maxval,0 minval
UNION ALL
SELECT '>=10' word,2147483646 maxval,10 minval
) t1 LEFT JOIN Replicant on Gen BETWEEN t1.minval AND t1.maxval
GROUP BY t1.word
Results:
| word | Count |
|------|-------|
| <10 | 2 |
| >=10 | 0 |
You can use left join:
SELECT v.Gen, COUNT(r.gen) as cnt
FROM (VALUES (NULL, 10, '<10'),
(10, NULL, '>=10')
) v(lo, hi, gen) LEFT JOIN
Replicant r
ON (r.gen >= v.lo OR v.lo IS NULL) AND
(r.gen < v.hi OR v.hi IS NULL)
GROUP BY v.gen;
You can also use conditional aggregation and unpivoting:
select v.*
from (select sum(case when r.gen < 10 then 1 else 0 end) as gen_1,
sum(case when r.gen >= 10 then 1 else 0 end) as gen_2
from replicant r
) r cross apply
(values (gen_1, '<10'), (gen_2, '>=10')
) v(cnt, gen);
I am looking for the least of three columns (Market, LiFo, Wgtd_Avg). This I can do, but exclude any of the three that are equal to zero.
I only want to find the least of those > zero.
SELECT Market, LiFo, Wgtd_Avg,
(
CASE
WHEN Market < LiFo AND Market < Wgtd_Avg AND Market > 0 THEN Market
WHEN LiFo < Wgtd_Avg AND LiFo > 0 THEN LiFo
WHEN Wgtd_Avg > 0 THEN Wgtd_Avg
ELSE 0
END
) AS LeastOfThree
FROM VF_CasINV_Cost
Original answer:
SELECT min(Value) FROM
(
SELECT Market as Value FROM VF_CasINV_Cost WHERE Market > 0
UNION
SELECT Wgtd_Avg as Value FROM VF_CasINV_Cost WHERE Wgtd_Avg > 0
UNION
SELECT LiFo as Value FROM VF_CasINV_Cost WHERE LiFo > 0
) union_table
Edited after comments:
SELECT Market, Wgtd_Avg, LiFo, min(least) AS leastOfThree FROM
(
SELECT min(market) as market, min(Market) as least FROM VF_CasINV_Cost WHERE Market > 0
UNION
SELECT min(Wgtd_avg) as Wgtd_Avg, min(Wgtd_Avg) as least FROM VF_CasINV_Cost WHERE Wgtd_Avg > 0
UNION
SELECT min(lifo) as LiFo, min(lifo) as least FROM VF_CasINV_Cost WHERE LiFo > 0
) as union_table
I'm away from a computer with a sql sever, so can't test this at moment, but it should be close to working... I'll test it and edit as soon as I'm back.
SELECT
MIN(
CASE x.f
WHEN 1 THEN t.Market
WHEN 2 THEN t.Wgtd_Avg
WHEN 3 THEN t.LiFo
END
) AS MinValue
FROM VF_Cas_INV_Cost t
INNER JOIN (SELECT 1 UNION ALL SELECT 2 UNION ALL SELECT 3) x (f)
ON CASE x.f
WHEN 1 THEN t.Market
WHEN 2 THEN t.Wgtd_Avg
WHEN 3 THEN t.LiFo
END > 0