SQL Server - SELECT DISTINCT depending on another column value - sql

I got a table like this, and there's on input parameter RevParam:
Key Rev IsCurrent
=====================
abc 0 TRUE
def 0 TRUE
ghj 2 FALSE
ghj 0 TRUE
klm 0 TRUE
def 1 FALSE
abc 1 FALSE
abc 2 FALSE
Where I want Key to be a unique value. If RevParam is set all rows with that Rev value should be viewed, the missing Key should have: revision 0. Like this:
Result if RevParam = 1
abc 1 FALSE
def 1 FALSE
ghj 0 TRUE
klm 0 TRUE
Result if revisionParameter = 0
abc 0 TRUE
def 0 TRUE
ghj 0 TRUE
klm 0 TRUE
This has been buggering me all day, please help me out!

WITH records
AS
(
SELECT [key], [rev], [IsCurrent],
ROW_NUMBER() OVER(PARTITION BY [key]
ORDER BY CASE WHEN [rev] = 1 -- <<== change REV value here
THEN 0 ELSE 1 END) rn
FROM tableName
WHERE [Rev] IN (1,0)
)
SELECT [key], [rev], [IsCurrent]
FROM records
WHERE rn = 1
SQLFiddle Demo for 1
SQLFiddle Demo for 0

Result if RevParam = 1
abc 1 FALSE
def 1 FALSE
ghj 0 TRUE
klm 0 TRUE
it has rev value 0 as well as 1. Please specify clearly

Related

BigQuery. CASE WHEN

I am working on BigQuery.
I need to created a query that counts if the version is a fix or not. The first version is not a fix and the ones that follow are a fix. Unless the first version has been created by system, in that case, the first and second versions are not a fix.
Now my query count only the first version as a non-fix, regardless of who created it.
My query is:
Select
CASE WHEN ROW_NUMBER()
OVER (PARTITION BY id_site ORDER BY timestamp ASC) = 1 THEN false ELSE true END is_fix,
FROM table1
Table1
ID ID_site Timestamp Version version_created_by
1 1 1/1/2022 4624653 system
2 1 1/2/2022 4624651 1234
3 1 1/3/2022 4624655 4567
4 2 5/2/2022 4567830 1234
5 2 5/3/2022 4567835 5678
6 3 5/4/2022 7567836 8907
7 3 5/5/2022 7890000 9807
Expected result:
ID ID_site Timestamp Version version_created_by is_fix
1 1 1/1/2022 4624653 system FALSE
2 1 1/2/2022 4624651 1234 FALSE
3 1 1/3/2022 4624655 4567 TRUE
4 2 5/2/2022 4567830 1234 FALSE
5 2 5/3/2022 4567835 5678 TRUE
6 3 5/4/2022 7567836 8907 FALSE
7 3 5/5/2022 7890000 9807 TRUE
Try below approach
SELECT
*,
CASE WHEN ROW_NUMBER() OVER (
PARTITION BY id_site
ORDER BY timestamp DESC
) <= t.cnt
THEN true ELSE false
END is_fix,
FROM (
Select
*,
CASE WHEN version_created_by = 'system' THEN 2 ELSE 1 END cnt
FROM table1
) as t
ORDER BY id
my test data & result are ...
id id_site timestamp version version_created_by
1 1 2022-01-01T00:00:00Z 4624653 system
2 1 2022-01-02T00:00:00Z 4624651 1234
3 1 2022-01-03T00:00:00Z 4624655 4567
4 2 2022-05-02T00:00:00Z 4567830 1234
5 2 2022-05-03T00:00:00Z 4567835 5678
6 3 2022-05-04T00:00:00Z 7567836 8907
7 3 2022-05-05T00:00:00Z 7890000 9807
id id_site timestamp version version_created_by cnt is_fix
1 1 2022-01-01T00:00:00Z 4624653 system 2 false
2 1 2022-01-02T00:00:00Z 4624651 1234 1 false
3 1 2022-01-03T00:00:00Z 4624655 4567 1 true
4 2 2022-05-02T00:00:00Z 4567830 1234 1 false
5 2 2022-05-03T00:00:00Z 4567835 5678 1 true
6 3 2022-05-04T00:00:00Z 7567836 8907 1 false
7 3 2022-05-05T00:00:00Z 7890000 9807 1 true
To match the format with the expected result,
SELECT * EXCEPT (cnt)
FROM (
SELECT
*,
CASE WHEN ROW_NUMBER() OVER (
PARTITION BY id_site
ORDER BY timestamp DESC
) <= t.cnt
THEN true ELSE false
END is_fix,
FROM (
Select
*,
CASE WHEN version_created_by = 'system' THEN 2 ELSE 1 END cnt
FROM table1
) as t
)
ORDER BY id
You can check if the 1st version was created by 'system' with FIRST_VALUE() window function:
SELECT *,
CASE ROW_NUMBER() OVER (PARTITION BY id_site ORDER BY timestamp)
WHEN 1 THEN false
WHEN 2 THEN FIRST_VALUE(version_created_by) OVER (PARTITION BY id_site ORDER BY timestamp) <> 'system'
ELSE true
END is_fix
FROM table1;
See the demo (for MySql).

SQL To count values of multiple columns

I have a table, with columns like this:
name1,name2,name_thesame,adress1,adress2,adress_thesame,city1,city2,city_thesame
In all columns ending with _thesame, there is a true or false depending if name1 and name2 are the same, same with adress etc etc.
I now need a query that returns a count how many true and false i got for each of the _thesame columns.
Cant wrap my head around how to do this query - any body got some ideas or pointers? Thanks
For a single property you can do:
select name_thesame, count(*)
from table
group by name_thesame
This will give you results like:
true 10
false 15
If you want to have it as a list for multiple columns, you can just union the queries:
select 'Name', name_thesame, count(*)
from table
group by name_thesame
union
select 'Address', adress_thesame, count(*)
from table
group by adress_thesame
getting:
Name true 10
Name false 15
Address true 20
Address false 5
This is another option:
SELECT SUM(CASE WHEN name_thesame = true THEN 1 ELSE 0 END) as nametrue,
SUM(CASE WHEN name_thesame = false THEN 1 ELSE 0 END) as namefalse,
SUM(CASE WHEN adress_thesame = true THEN 1 ELSE 0 END) as adresstrue,
SUM(CASE WHEN adress_thesame = false THEN 1 ELSE 0 END) as adressfalse,
SUM(CASE WHEN city_thesame = true THEN 1 ELSE 0 END) as citytrue,
SUM(CASE WHEN city_thesame = false THEN 1 ELSE 0 END) as cityfalse
FROM yourTable
You can tweak it to deal with NULLs as well if relevant:
...
CASE WHEN name_thesame = false OR name_thesame IS NULL THEN 1 ELSE 0 END
...
or either NVL(), ISNULL(), IFNULL() or COALESCE(), depending on the DBMS you're using (syntax is always the same):
...
CASE WHEN COALESCE(name_thesame, false) = false THEN 1 ELSE 0 END
...
Result:
nametrue | namefalse | adresstrue | adressfalse | citytrue | cityfalse
5 | 7 | 2 | 1 | 10 | 8

SQL Grouping with a logic check on another column?

Lets say that I have the following table:
id param result
1 AAA TRUE
1 AAA FALSE
1 AAA FALSE
1 BBB TRUE
1 CCC TRUE
2 AAA TRUE
2 CCC TRUE
3 AAA FALSE
3 AAA FALSE
3 AAA FALSE
3 CCC TRUE
3 BBB TRUE
Is there a way to group by the [param] column so that the [result] will show TRUE if any of the corresponding results are TRUE and show FALSE if none are TRUE? Below is an example of what I am aiming for:
id param result
1 AAA TRUE
1 BBB TRUE
1 CCC TRUE
2 AAA TRUE
2 CCC TRUE
3 AAA FALSE
3 CCC TRUE
3 BBB TRUE
Here is a sketch of code that will work. You just need to put in the right constants for result:
select id, param,
(case when sum(case when result = TRUE then 1 else 0 end) > 0
then TRUE else FALSE
end)
from table t
group by id, param;
SQL Server does not have a native boolean type and doesn't understand "true" and "false". For some representations (such as 'TRUE' and 'FALSE'), the following will work:
select id, param, max(result) as result
from table t
group by id, param;

sql server count distinct value of a field

I have 2 tables : Contents and Packs
In Content columns are like this:
Id Name IsPerishable IsSpecial IsDanger
----------------------------------------------------------
1 Paper False False False
3 Fruit True False False
5 NewsPaper False True False
6 Radioactive False False True
7 Foods True False False
In Packs columns are like this:
Id From To ContentId
---------------------------------------
1 ABZ ATL 3
2 ANU ATL 5
3 BAQ ATL 7
4 BTS BAQ 6
5 FRL BAQ 5
Now I want a result that groups every 'To' then shows separate value of IsPerishable / IsSpecial / IsDanger
like this:
To Perishable Special Danger
-----------------------------------------------
ATL 2 1 0
BAQ 0 1 1
I try use some query but none of them has worked correctly:
select Name,
case
when IsSpecial = 1 then count(IsSpecial)
when IsPerishable = 1 then count(IsPerishable)
when IsDanger = 1 then count(IsDanger)
end as 'Content'
from Contents
group by IsSpecial , IsPerishable , IsDanger
select To,count(DISTINCt Id) as 'Count'
FROM Packs
GROUP BY To
try this
Select To,
(Select count(*) from Content c where c.Id= p.Id and c.IsSpecial=1) as Special,
(Select count(*) from Content c where c.Id= p.Id and c.Isperishable=1) as Perishable,
(Select count(*) from Content c where c.Id= p.Id and c.Isperishable=1) as Danger
from
pack p
group by To
SELECT P.To, SUM(Perishable), SUM(Special),SUM(Danger) FROM
(
SELECT Id,
CASE IsPerishable WHEN true THEN 1 ELSE 0 END AS Perishable,
CASE IsSpecial WHEN true then 1 ELSE 0 END AS Special,
CASE IsDanger WHEN true then 1 ELSE 0 END AS Danger
FROM Contents
) C
Right Join Packs P
on P.ContentId=C.Id
Group BY P.to

Split single column to multiple

My table look like this:
id customer_code comments
-----------------------------------
1 Dilbert true
2 Dilbert false
3 Wally true
4 wally true
5 wally false
I need to results look like this:
id customer_code x1 x2
------------------------------
1 Dilbert ture
2 Dilbert false
3 wally ture
4 wally ture
5 wally false
SELECT [id], [customer_code],
CASE [comments] WHEN 'TRUE' THEN 'TRUE' ELSE NULL END AS X1,
CASE [comments] WHEN 'FALSE' THEN 'FALSE' ELSE NULL END AS X2
FROM Table1;
FIDDLE