I have three tables, DailyFieldRecord, AB953,and Lookup. The DailyFieldRecord table contains DailyFieldRecordID.The AB953 table contains DailyFieldRecordID,GroupID,LookupID, and PersonID. The Lookup table contains GroupID, Description, and LookupID. I'm trying to display the persons ethnicity, age, and gender in the same row based on each DailyFieldRecordID and PersonID. The problem I'm having is that the descriptions of ethnicity, age, and gender are in the same column in the lookup table. I've tried different ways, but am only able to get the correct information for one person. Any input would be helpful.
DailyFieldRecord: AB953:
DailyFieldRecordID DailyFieldRecordID: LookupID: GroupID: PersonID:
1111 1111 1260 300 1
1111 1262 200 1
1111 1264 310 1
1111 1258 300 2
1111 1261 200 2
1111 1265 310 2
Lookup:
GroupID: Description: LookupID:
300 white 1260
300 latin 1258
200 17 1262
200 18 1261
310 male 1264
310 female 1265
Select ab.DailyFieldRecordID, lkp.Description as
Ethinicity,lkp2.Description as Age, lkp3.Description as Gender,
ab.PersonID
FROM DailyFieldRecord dfr
LEFT JOIN AB953 ab ON ab.DailyFieldRecordID=dfr.DailyFieldRecordID and
ab.GroupID=300 and ab.PersonID=1
LEFT JOIN AB953 ab2 ON ab2.DailyFieldRecordID=dfr.DailyFieldRecordID and
ab2.GroupID=200 and ab2.PersonID=1
LEFT JOIN AB953 ab3 ON ab3.DailyFieldRecordID=dfr.DailyFieldRecordID and
ab3.GroupID=310 and ab3.PersonID=1
LEFT JOIN Lookup lkp ON lkp.LookupID=ab.ItemID
LEFT JOIN Lookup lkp2 ON lkp2.LookupID=ab2.ItemID
LEFT JOIN Lookup lkp3 ON lkp3.LookupID=ab3.ItemID
Current output:
DailyFieldRecordID: Ethnicity: Age: Gender: PersonID:
1111 white 17 male 1
Expected output:
DailyFieldRecordID: Ethnicity: Age: Gender: PersonID:
1111 white 17 male 1
1111 latin 18 female 2
Though i must say, this is very bad DB design, Yet you are getting only first person ID coz you are using PersonID = 1 in the query. Please try below query removing PersonID = 1.
Select ab.DailyFieldRecordID
,MAX(CASE WHEN lkp.GroupID = 300 THEN lkp.Description) as Ethinicity
,MAX(CASE WHEN lkp.GroupID = 200 THEN lkp.Description) as Age
,MAX(CASE WHEN lkp.GroupID = 310 THEN lkp.Description) as Gender
,ab.PersonID
FROM DailyFieldRecord dfr
LEFT JOIN AB953 ab ON ab.DailyFieldRecordID=dfr.DailyFieldRecordID
LEFT JOIN Lookup lkp ON lkp.GroupID=ab.GroupID
GROUP BY ab.DailyFieldRecordID, ab.PersonID
Related
BACKGROUND
I have three large tables (employee_info, driver_info, school_info) that I have joined together on common attributes using a series of LEFT OUTER JOIN operations. After each join, the resulting number of records increased slightly, indicating that there are duplicate IDs in the data. To try and find all of the duplicates in the IDs, I dumped the ID columns into a temp table like so:
Original Dump of ID Columns
first_name
last_name
employee_id
driver_id
school_id
Mickey
Mouse
1234
abcd
wxyz
Donald
Duck
2423
heca
qwer
Mary
Poppins
1111
acbe
aaaa
Wiley
Cayote
1234
strf
aaaa
Daffy
Duck
1256
acbe
pqrs
Bugs
Bunny
9999
strf
yxwv
Pink
Panther
2222
zzzz
zzaa
Michael
Archangel
0000
rstu
aaaa
In this overly simplified example, you will see that IDs 1234 (employee_id), strf (driver_id), and aaaa (school_id) are each duplicated at least once. I would like to add a count column for each of the ID columns, and populate them with the count for each ID used, like so:
ID Columns with Counts
first_name
last_name
employee_id
employee_id_count
driver_id
driver_id_count
school_id
school_id_count
Mickey
Mouse
1234
2
abcd
1
wxyz
1
Donald
Duck
2423
1
heca
1
qwer
1
Mary
Poppins
1111
1
acbe
1
aaaa
3
Wiley
Cayote
1234
2
strf
2
aaaa
3
Daffy
Duck
1256
1
acbe
1
pqrs
1
Bugs
Bunny
9999
1
strf
2
yxwv
1
Pink
Panther
2222
1
zzzz
1
zzaa
1
Michael
Archangel
0000
1
rstu
1
aaaa
3
You can see that IDs 1234 and strf each have 2 in the count, and aaaa has 3. After generating this table, my goal is to pull out all records where any of the counts are greater than 1, like so:
All Records with One or More Duplicate IDs
first_name
last_name
employee_id
employee_id_count
driver_id
driver_id_count
school_id
school_id_count
Mickey
Mouse
1234
2
abcd
1
wxyz
1
Mary
Poppins
1111
1
acbe
1
aaaa
3
Wiley
Cayote
1234
2
strf
2
aaaa
3
Bugs
Bunny
9999
1
strf
2
yxwv
1
Michael
Archangel
0000
1
rstu
1
aaaa
3
Real World Perspective
In my real-world work, the JOIN'd table contains 100 columns, 15 different ID fields and over 30,000 records, and the final table came out to be 28 more than the original. This may seem like a small amount, but each of the 28 represent a broken link that we must fix.
Is there a simple way to get the counts populated like in the second table above? I have been wrestling with this for hours already, and have not been able to make this work. I tried some aggregate functions, but they cannot be used in table UPDATE operations.
The COUNT function, when used as an analytic function, can do what you want here, e.g.
WITH cte AS (
SELECT *,
COUNT(employee_id) OVER (PARTITION BY employee_id) employee_id_count,
COUNT(driver_id) OVER (PARTITION BY driver_id) driver_id_count,
COUNT(school_id) OVER (PARTITION BY school_id) school_id_count
FROM yourTable
)
SELECT *
FROM cte
WHERE
employee_id_count > 1
driver_id_count > 1
school_id_count > 1;
I'm trying to write a query that will include a count for the primary and secondary activity only when Group ID = 260 and Item id in(1302,1303,1305,1306) for each individual RecordID. So far I have been able to single out the rows with those conditions, but I only want to count the primary and secondary activities once(because the Primary and Secondary activities are the same for their corresponding RecordID regardless of how many rows there are), if they aren't null, regardless of how many RecordID's match those conditions.
RecordID: GroupID: ItemID: PrimActivity: SecActivity:
320 260 1302 36 0
320 260 6456 36 0
320 312 1303 36 0
560 400 1302 46 48
560 312 1305 46 48
460 260 1305 45 56
460 260 1302 45 56
Result I'm getting:
RecordID: Count:
320 2
460 4
Expected result:
RecordID: Count:
320 1
460 2
SELECT dfr.RecordID,
COUNT(CASE WHEN dfr.PrimActivity <> 0 and a.GroupID =260 then 1
ELSE NULL END) +
COUNT(CASE WHEN dfr.SecActivity <> 0 and a.GroupID =260 then 1 ELSE
NULL END) AS Count
From ActivityItem ai
Join DailyRecord dfr on ai.PrimActivity = dfr.PrimActivity
Join AreaInfo af on af.AreaInfoID = dfr.AreaInfoID
Join Information a on dfr.RecordID = a.RecordID
Join Lookup lp on lp.ItemID = a.ItemID
WHERE a.GroupID like '260' and EXISTS(
SELECT b.RecordID, b.GroupID, b.ItemID
FROM Areainfo b
where a.RecordID=b.RecordID and b.ItemID IN(1302,1303,1305,1306)
GROUP BY dfr.RecordID
You should be more clear when you explain the structure of tables you are using. However, I reach the expected result starting from your sample table doing this:
SELECT RecordID,COUNT(*) as Count
FROM (SELECT DISTINCT RecordID,ItemID,PrimActivity,SecActivity
FROM [TABLE YOU POSTED]
WHERE GroupID = 260 and ItemID in (1302,1303,1305,1306) ) A
GROUP BY RecordID
I have a table that contains 3 columns of ids, clothes, shoes, customers and relates them.
I have a query that works fine :
select clothes, shoes from table where customers = 101 (all clothes and shoes of customer 101). This returns
clothes - shoes (SET A)
1 6
1 2
33 12
24 null
Another query that works fine :
select clothes ,shoes from table
where customers in
(select customers from table where clothes = 1 and customers <> 101 ) (all clothes and shoes of any other customer than 101, with specified clothes). This returns
shoes - clothes(SET B)
6 null
null 24
1 1
2 1
12 null
null 26
14 null
Now I want to get all clothes and shoes from SET A that are not in SET B.
So (example) select from SET A where NOT IN SET B. This should return just clothes 33, right?
I try to convert this to a working query :
select clothes, shoes from table where customers = 101
and
(clothes,shoes) not in
(
select clothes,shoes from
table where customers in
(select customers from table where clothes = 1 and customers <> 101 )
) ;
I tried different syntaxes, but the above looks more logic.
Problem is I never get clothes 33, just an empty set.
How do I fix this? What goes wrong?
Thanks
Edit , here is the contents of the table
id shoes customers clothes
1 1 1 1
2 1 4 1
3 1 5 1
4 2 2 2
5 2 3 1
6 1 3 1
44 2 101 1
46 6 101 1
49 12 101 33
51 13 102
52 101 24
59 107 51
60 107 24
62 23 108 51
63 23 108 2
93 124 25
95 6 125
98 127 25
100 3 128
103 24 131
104 25 132
105 102 28
106 10 102
107 23 133
108 4 26
109 6 4
110 4 24
111 12 4
112 14 4
116 102 48
117 102 24
118 102 25
119 102 26
120 102 29
122 134 31
The except clause in PostgreSQL works the way the minus operator does in Oracle. I think that will give you what you want.
I think notionally your query looks right, but I suspect those pesky nulls are impacting your results. Just like a null is not-NOT equal to 5 (it's nothing, therefore it's neither equal to nor not equal to anything), a null is also not-NOT "in" anything...
select clothes, shoes
from table1
where customers = 101
except
select clothes, shoes
from table1
where customers in (
select customers
from table1
where clothes = 1 and customers != 101
)
For PostgreSQL null is undefined value, so You must get rid of potential nulls in your result:
select id,clothes,shoes from t1 where customers = 101 -- or select id...
and (
clothes not in
(
select COALESCE(clothes,-1) from
t1 where customers in
(select customers from t1 where clothes = 1 and customers <> 101 )
)
OR
shoes not in
(
select COALESCE(shoes,-1) from
t1 where customers in
(select customers from t1 where clothes = 1 and customers <> 101 )
)
)
if You wanted unique pairs you would use:
select clothes, shoes from t1 where customers = 101
and
(clothes,shoes) not in
(
select coalesce(clothes,-1),coalesce(shoes,-1) from
t1 where customers in
(select customers from t1 where clothes = 1 and customers <> 101 )
) ;
You can't get "clothes 33" if You are selecting both clothes and shoes columns...
Also if u need to know exactly which column, clothes or shoes was unique to this customer, You might use this little "hack":
select id,clothes,-1 AS shoes from t1 where customers = 101
and
clothes not in
(
select COALESCE(clothes,-1) from
t1 where customers in
(select customers from t1 where clothes = 1 and customers <> 101)
)
UNION
select id,-1,shoes from t1 where customers = 101
and
shoes not in
(
select COALESCE(shoes,-1) from
t1 where customers in
(select customers from t1 where clothes = 1 and customers <> 101)
)
And Your result would be:
id=49, clothes=33, shoes=-1
(I assume that there aren't any clothes or shoes with id -1, You may put any exotic value here)
Cheers
I've searched but so far don't find answer fits my situation.
How do you write select statement to selecting out duplicate records within the same table column and list them (so not group by it)??
example: to find duplicates for contract_id column and list them out
ID contract_id Sales1 Sales2
1 12345 100 200
2 54321 300 674
3 12345 343 435
4 09876 125 654
5 54321 374 233
6 22334 543 335
Result should look like this with order by contract_id as well:
ID contract_id Sales1 Sales2
1 12345 100 200
3 12345 343 435
2 54321 300 674
5 54321 374 233
You could use a subquery on the count >1
select * from my_table
where contract_id in (
select contract_id
from my_table
group by contract_id
having count(*) > 1
)
In my Table 1, It may have AND have a null entry in the address column to corresponding record OR not have a matching entry in Table 2.
I want to present all the records in Table 1 but also present corresponding entries from Table 2. My RESULT is what I am trying to achieve.
Table 1
ID First Last
1 John Smith
2 Bob Long
3 Bill Davis
4 Sam Bird
5 Tom Fenton
6 Mary Willis
Table 2
RefID ID Address
1 1 123 Main
2 2 555 Center
3 3 626 Smith
4 4 412 Walnut
5 1
6 2 555 Center
7 3
8 4 412 Walnut
Result
Id First Last Address
1 John Smith 123 Main
2 Bob Long 555 Center
3 Bill Davis 626 Smith
4 Sam Bird 412 Walnut
5 Tom Fenton
6 Mary Willis
You need an outer join for this:
SELECT * FROM Table1 t1 LEFT OUTER JOIN Table2 t2 ON t1.ID = t2.RefID
How do you join those two tables? If table 2 have more than 1 matched address, how do you want display them? Please clarify in your question.
Here is a query based on my assumptions.
SELECT
ID, First, Last,
Address = (SELECT MAX(Address) FROM Table2 t2 WHERE t1.ID = t2.ID)
FROM Table1 t1