I have a table where I am determining whether a person's ID number exists across multiple databases. If the ID exists in only one database, then I would like to add another column that labels the person as "UNIQUE"; otherwise, it should be labeled as "NOT UNIQUE".
My query thus far is set up like this:
/* CTE that creates a long column of all distinct PersonID's across three databases */
WITH cte as
(SELECT DISTINCT t1.*
FROM
(SELECT PersonID FROM DB_1.dbo.Persons
UNION
SELECT PersonID FROM DB_2.dbo.Persons
UNION
SELECT PersonID FROM DB_3.dbo.Persons)
t1)
/* Use CASE WHEN statements to check if Person exists in three other tables in DB_1, DB_2, and DB_3 */
SELECT PersonID,
CASE WHEN PersonID IN (SELECT PersonID FROM DB_1.dbo.Table_1
UNION
SELECT PersonID FROM DB_1.dbo.Table_2
UNION
SELECT PersonID FROM DB_1.dbo.Table_3)
THEN 'TRUE'
ELSE 'FALSE'
END AS IN_DB_1,
CASE WHEN PersonID IN (SELECT PersonID FROM DB_2.dbo.Table_1
UNION
SELECT PersonID FROM DB_2.dbo.Table_2
UNION
SELECT PersonID FROM DB_2.dbo.Table_3)
THEN 'TRUE'
ELSE 'FALSE'
END AS IN_DB_2,
CASE WHEN PersonID IN (SELECT PersonID FROM DB_3.dbo.Table_1
UNION
SELECT PersonID FROM DB_3.dbo.Table_2
UNION
SELECT PersonID FROM DB_3.dbo.Table_3)
THEN 'TRUE'
ELSE 'FALSE'
END AS IN_DB_3
FROM cte
The results look like this:
PersonID IN_DB_1 IN_DB_2 IN_DB_3
---------|----------|----------|----------|
001 TRUE FALSE FALSE
002 FALSE TRUE TRUE
003 TRUE FALSE FALSE
004 FALSE TRUE FALSE
005 TRUE FALSE TRUE
As can be seen, PersonID numbers 001, 003, and 004 appear only in one database.
I would like to add a fifth column called "PID_UNIQUE" that counts the number of "TRUE" text values across the columns and specifies whether the person is unique.
It should look like this:
PersonID IN_DB_1 IN_DB_2 IN_DB_3 PID_UNIQUE
---------|----------|----------|----------|-----------|
001 TRUE FALSE FALSE UNIQUE
002 FALSE TRUE TRUE NOT UNIQUE
003 TRUE FALSE FALSE UNIQUE
004 FALSE TRUE FALSE UNIQUE
005 TRUE FALSE TRUE NOT UNIQUE
I assume this would be set up using another CASE WHEN expression. I am a little stuck as to how I could write that out to count across the three "IN_DB_no" columns.
I tried this:
CASE WHEN COUNT('TRUE') = 1
THEN 'UNIQUE'
ELSE 'NOT UNIQUE'
END AS PID_UNIQUE
However, it returned a column where all records were unique, which is not what I need.
I have a table where I am determining whether a person's ID number exists across multiple databases.
Your sample query references many more tables than this suggests. Hence, it seems much more complicated than necessary.
Let me assume that there are really three tables, one in each database. I see just an aggregation after UNION ALL:
SELECT PersonID, MAX(in_1), MAX(in_2), MAX(in_3),
(CASE WHEN MAX(in_1) + MAX(in_2) + MAX(in_3) = 1 THEN 'UNIQUE'
ELSE 'NOT UNIQUE'
END) as pid_Unique
FROM ((SELECT DISTINCT PersonID, 1 as in_1, 0 as in_2, 0 as in_3
FROM DB_1.dbo.Persons
) UNION ALL
(SELECT DISTINCT PersonID, 0 as in_1, 1 as in_2, 0 as in_3
FROM DB_2.dbo.Persons
) UNION ALL
(SELECT DISTINCT PersonID, 0 as in_1, 0 as in_2, 1 as in_3
FROM DB_3.dbo.Persons
)
) p
GROUP BY PersonId;
I figured out a solution that works for me using the CROSS APPLY operator, along with a CASE / WHEN expression.
Basically, I added an additional column to the table I already made.
The query looked like this:
SELECT * FROM My_New_DB.dbo.My_New_Tbl
CROSS APPLY (
SELECT CASE WHEN 1 = (SELECT COUNT(*)
FROM (VALUES (IN_DB_1), (IN_DB_2), (IN_DB_3)) C (Val)
WHERE Val = 'TRUE')
THEN 'UNIQUE'
ELSE 'NOT UNIQUE'
END AS UNIQUE_ID
) A
Simply put, when 1 = 1, it is unique.
Related
suppose I have two tables A and B, both with only 1 column name. Some rows appear in both tables while some are exclusive to one table. I want to union these two tables together into a table C that has 3 columns name, is_in_A and is_in_B. For a row that appeared in both A and B, the last 2 fields would both be 'true'. For a row that appeared in only A, only is_in_A would be 'true' and is_in_B would be false.
My current solution works like this:
Create three temporary tables that all have the columns name, is_in_A and is_in_B:
A_join_B that has all rows that are in A and B. is_in_A and is_in_B are both true for every row in this table
A_minus_B that has all rows that are exclusive to A. is_in_A is true and is_in_B is false for every row in that table.
B_minus_A respectively.
Now I union all 3 tables together to get my result.
Is there a better/easier way to do this (ideally as a single union without any temporary tables)?
You can do it with a FULL join of the tables:
SELECT COALESCE(a.name, b.name) AS name,
CASE WHEN a.name IS NULL THEN false ELSE true END AS is_in_A,
CASE WHEN b.name IS NULL THEN false ELSE true END AS is_in_B
FROM a FULL OUTER JOIN b
ON b.name = a.name
If your database does not support boolean values like true and false, change to 1 and 0 or string literals 'true' and 'false'.
See a simplified demo.
You can use union all and aggregation:
select name, sum(in_a), sum(in_b)
from ((select name, 1 as in_a, 0 as in_b
from a
) union all
(select name, 0, 1
from b
)
) ab
group by name;
I am trying to come up with a query that returns a list of parts where all of the flags for that one part are false, and the returned list should only have one record returned for that part.
Part Revision Flag
Part1| A | true
Part1| B | false
Part2| C | false
Part2| D | false
Part2| E | false
Part3| A | true
Part4| F | false
Output:
Part Revision Flag
Part2| C(or any other revision) | false
Part4| F | false
Part1 and Part3 have at least 1 flag set to true so they don't get outputted. Part2 and 4 have no flags at all set to true, and Part2 only returns 1 row for all of them.
SELECT DISTINCT [PartNum],[RevisionNum],[Flag]
FROM [Prod].[Erp].[PartRev]
WHERE RevisionNum is not null AND Approved = 0
ORDER BY PartNum
GROUP BY [PartNum],[RevisionNum],[Flag]
So far I can get one row per part number, but it will return just one row even if one of the others for that part number is true.
What gets returned:
Part Revision Flag
Part1| B | false
Part2| C | false
Part4| F | false
Does anyone know how to fix this?
Another option
Select Part
,Revision = max(Revision)
,Flag = max(flag)
from YourTable
Group By Part
Having max(Flag)='false'
Returns
Part Revision Flag
Part2 E false
Part4 F false
First, select all of the records that have flag = true
SELECT DISTINCT Part FROM PartRev WHERE flag = 1 --or whatever your RDBMS uses for a true value
Then, select all the distinct records that are not included in the first query. So, the query would look like this
SELECT Part, MIN(Revision), flag
FROM PartRev WHERE Part NOT IN (
SELECT DISTINCT Part FROM PartRev WHERE flag = 1
)
GROUP BY Part, flag
You can do this with a WHERE NOT EXISTS to not pull any records that have a true flag.
It also looks like you're wanting to pull the most recent revision for the part as the record returned, which can be accomplished via a ROW_NUMBER() and selecting just the most recent record.
;With Cte As
(
Select *,
Row_Number() Over (Partition By Part Order By Revision Desc) As RN
From [Prod].[Erp].[PartRev] P1
Where RevisionNum is not null
And Approved = 0
And Not Exists
(
Select *
From [Prod].[Erp].[PartRev] P2
Where P1.Part = P2.Part
And P2.Flag = 'true'
)
)
Select Part, Revision, Flag
From Cte
Where RN = 1
How about something like this, as a more general formulation, because the case statement can be made quite complex:
SELECT
SP.Part
, SP.Revision
, SP.Flag
FROM (
SELECT
Part
, Count(Part) as TC
, SUM( CASE Flag WHEN 1 THEN 0 ELSE 1 END ) FC
, MAX(Revision) AS Revision
, MAX(flag) AS Flag
FROM test
GROUP BY Part
) SP
WHERE SP.TC=SP.FC
I have a table where the id field (not a primary key) contains either 1 or null. Over the past several years, any given part could have been entered multiple times with one, or both of these possible options.
I'm trying to write a statement that will return some value if there is ever a 1 associated with the select statement. There are lots of semi-duplicate rows, some with 1 and some with null, but if there is ever a 1, I want to return true, and if there are only null values, I want to return false. I'm not sure how to code this though.
If this is my SELECT part,id from table where part = "ABC1234" statement
part id
ABC1234 1
ABC1234 null
ABC1234 null
ABC1234 null
ABC1234 1
I want to write a statement that returns true, because 1 exists in at least one of these rows.
The closest I've come to this is by using a CASE statement, but I'm not quite there yet:
SELECT
a1.part part,
CASE WHEN a2.id is not null
THEN
'true'
ELSE
'false'
END AS id
from table.parts a1, table.ids a2 where a1.part = "ABC1234" and a1.key = a2.key;
I also tried the following case:
CASE WHEN exists
(SELECT id from table.ids where id = 1)
THEN
but I got the error subqueries are not supported in the select list
For the above SELECT statement, how do I return 1 single line that reads:
part id
ABC1234 true
You can use conditional aggregation to check if a part has atleast one row with id=1.
SELECT part,'True' id
from parts
group by part
having count(case when id = 1 then 1 end) >= 1
To return false when the id's are all nulls use
select part, case when id_true>=1 then 'True'
when id_false>=1 and id_true=0 then 'False' end id
from (
SELECT part,
count(case when id = 1 then 1 end) id_true,
count(case when id is null then 1 end) id_false,
from parts
group by part) t
I have a collection of parent items and each has an indeterminate set of child items. Each child item as an attribute that is X or NULL. (Apologies for the odd Boolean structure, but that's what I have to work with.)
Parent Child Attribute
------ ----- ---------
A 1 X
A 2 X
A 3 NULL
B 1 X
B 2 NULL
B 3 NULL
C 1 X
C 2 X
D 1 NULL
E 1 NULL
E 2 NULL
I want to identify parent items as True or False based on the child items. One NULL value will result in a False return for that parent item. Here are the desired results:
A False
B False
C True
D False
E False
The ideal solution would even handle a parent that has no child records (result is False).
I can do this using temporary tables. That solution is fairly long and I don't think presenting it would add any value to this post.
How can I do this with an SQL query using no temporary tables?
I would present "things I've tried" but I don't know enough how to even start.
I don't think this is equivalent to nor. You just want to know if any values are NULL -- or equivalently if all values are 'X'. Use case and aggregation:
select parent,
(case when count(*) = count(attribute) then 'true'
else 'false'
end)
from t
group by parent;
To handle a parent with no children requires a list of parents, separate from this list:
select p.parent,
(case when count(*) = count(t.attribute) and count(t.parent) > 0 then 'true'
else 'false'
end)
from parents p left join
t
on p.parent = t.parent
group by p.parent;
As a reminder, count(*) counts the number of rows in the result set. COUNT() with an expression (including a column) counts the number of non-NULL values. When these are the same, there are no non-NULL values.
You can do this via aggregates..,when no attributes,i have kept the column as blank..
In summary assign true or false to each row and get min value
create table #test
(
id int,
name char(2)
)
insert into #test
select 1,'x'
union all
select 1,null
union all
select 2,null
union all
select 3,''
with cte
as
(
select id,b.*
from #test t1
cross apply
(
select case when name is null or name='' then 'False' Else 'True' end as 'chk' from #test t2 where t2.id=t1.id ) b
)
select id,min(chk)
from
cte group by id
You can remove even cross apply:
with cte
as
(
select id,case when name is null or name='' then 'False' Else 'True' end as 'chk'
from #test t1
)
select id,min(chk)
from
cte group by id
Output:
1 False
2 False
3 False
My table holds type 2 change history; so if recordID 123 has a change made by a user, then 'latest_effective' gets set to FALSE and the newly created record with recordID 123 has 'latest_effective' set to TRUE.
I'm looking for a query that returns the new record & the record that was just changed with a third row that is TRUE if there is a change in that column and FALSE if not.
select RecordID,1 latest_effective,Column1,Column2, etc...
from YourTable
where latest_effective = 1
union all
select RecordID,0 latest_effective,Column1,Column2, etc...
from YourTable
where latest_effective = 0
union all
select t.RecordID,-1 latest_effective,
case t.Column1 when f.Column1 then 'FALSE' else 'TRUE' end AS Column1
case t.Column2 when f.Column2 then 'FALSE' else 'TRUE' end AS Column2, etc...
from YourTable AS t
inner join YourTable AS f
on f.RecordID = t.RecordID
and f.latest_effective = 0
where t.latest_effective = 1
order by RecordID,latest_effective desc