SQL Join from 2 Tables with Null Values - sql

I have 2 tables and want to pull the results back from them into one.
Now the Name field is a unique ID with multiple data attached to it, i.e. the dates and the times. I've simplified the data somewhat to post here but this is the general gist.
Table 1
Name Date
John 12th
John 13th
John 15th
John 17th
Table 2
Name Colour
John Red
John Blue
John Orange
John Green
Result Needed
Name Date Time
John 12th NULL
John 13th NULL
John 15th NULL
John 17th NULL
John NULL Red
John NULL Blue
John NULL Orange
John NULL Green
I'm currently performing a Left join to pull the data however it is posting the results next to each other like
John 12th Red

You want union all:
select name, date, null as colour
from t1
union all
select name, null, colour
from t2;
I took the liberty of naming the second column colour rather than time, simply because that makes more sense in the context of the question.

Related

Self JOIN to find the parent detail which matches with the row data -

I am trying to query in MS SQL and I can not resolve it. I have a table employees:
Id Name Surname FatherName MotherName WifeName Pincode isChild
-- ------- ------- ---------- ---------- -------- ------- -------
1 John Green James Sue null 101011 1
2 Michael Sloan Barry Lilly null 101011 1
3 Sally Green Andrew Molly Jemi 101011 1
4 Barry Sloan Soul Paul Lilly 101011 0
5 James Green Ned White Sue 101011 0
I want a query that selects rows where the father name and mother name of child matches with name and wife name. For the example table, where I want to return the result of rows where father and mother name matches the name and wife name column. For eg. id=1, where John's father name James and mother name Sue matches with id 5 which returns James as first name and Sue as wife name. So my query should return (this is my expected result)
Id Name Surname FatherName MotherName WifeName Pincode isChild
-- ------- ------- ---------- ---------- -------- ------- -------
5 James Green Ned White Sue 101011 0
4 Barry Sloan Soul Paul Lilly 101011 0
I tried with the below query but it checks for James only. How to change my query so that it checks all the names and returns the expected result.
select * FROM employees
where first_name like '%James%'
and wife_name like '%Sue%'
and pincode=101011;
Any tips on this will be really helpful. I am new to joins, need help on writing self join to get the result.
…
select *
from thetable as p -- the parent/father
where exists -- with one child at least
(
select *
from thetable as c
where c.fathername = p.name
and c.mothername = p.wifename
-- lastname?
)
Too long for a comment, but also not intended as a slam against what you are working with. Please take as constructive criticism.
Aside from VERY POOR DESIGN on the table content, getting that corrected before you get too deep into whatever you are working should be done first. A more typical design might be having a table of people. Now, to get the relationships you could do a couple ways. One is that on each individual person's record, you add 2 additional IDs. FatherID, MotherID. These IDs would join directly back to the child vs hard strings to match against. Take a surname like Smith or Jones. Then, look at the many instances of a "John Smith" may exist, yes a lot, and lower probability of finding a matching wife's name of Sue, Mary or whatever else name. But even that could lead to multiple possibilities. Yes, you are adding a PIN, but even a computer can generate a random pin of 1234.
By having the IDs, there is NO ambiguity of who the relationship is with.
If the data were slightly altered to something like
Id Name Surname FatherID MotherID SpouseID
-- ------- ------- ---------- ---------- --------
1 John Green 5 6 null
2 Michael Sloan 4 3 null
3 Lilly Sloan null null 4
4 Barry Sloan null null 3
5 James Green 9 10 6
6 Sue Green 7 8 5
7 Bill Jones null null 8
8 Martha Jones null null 7
9 Brian Green null null 10
10 Beth Smith-Green null null 9
So, in this modified example, you can see right away that ID#1 John Green has parents of Father (ID#5) is James and Mother (ID#6) is Sue. But even from this, James is a child to Father (ID#9) Brian and Mother (ID#10) Beth. This scenario is showing to a grand-parent level capacity and that each of James and Sue are also children but to their respective parents. Sue's parents of the Jones surname.
For Michael Sloan, parents of #4 Barry, and #3 Lilly.
And I additionally added a spouse ID. This prevents redundancy of people's names copied all over. Then you can query based on the child's parent's respective IDs to find out vs a hopeful name LIKE guess.
So, even though not solving a relatively simple query, fixing the underlying foundation of your database and is relations will, long-term, help ease your querying in the future.
Try this:
SELECT
T2.*
FROM Employee T1
JOIN Employee T2 ON T2.Name = T1.FatherName
AND T2.WifeName = T1.MotherName

How do I select a max date by person in a table

I am not too advanced with SSRS/SQL queries, and need to write a report that pulls out % allocations by person to then compare to a wage table to allocate the wages. These allocations change quarterly, but all allocations continue to be stored in the table. If a persons allocation did not change, they do NOT get a new entry in the table. Here is a sample table called Allocations.
First Name
Last Name
Date
Area
Percent
Smith
Bob
01/01/20
A
50.00
Smith
Bob
01/01/20
B
50.00
Doe
Jane
01/01/20
A
25.00
Doe
Jane
01/01/20
B
25.00
Doe
Jane
01/01/20
C
50.00
Doe
Jane
04/01/20
A
35.00
Doe
Jane
04/01/20
C
65.00
Wayne
Bruce
01/01/20
A
100.00
Wayne
Bruce
04/01/20
B
100.00
The results that I would want to have from this sample table when querying it are:
First Name
Last Name
Date
Area
Percent
Smith
Bob
01/01/20
A
50.00
Smith
Bob
01/01/20
B
50.00
Doe
Jane
04/01/20
A
35.00
Doe
Jane
04/01/20
C
65.00
Wayne
Bruce
04/01/20
B
100.00
However, I would also like to pull this by comparing it to a date that the user inputs, so that they could run this report at any point in time and get the correct "max" dates. So, for example, if there were also 7/1/20 dates in here, but the user input date was 6/30/20, I would NOT want to pull the 7/1/20 data. In other words, I would like to pull the rows with the maximum date by name w/o going over the user's input date.
Any idea on the best way to accomplish this?
Thanks in advance for any advice you can provide.
In SQL, ROW_NUMBER can be used to order records in groups by a particular field.
SELECT * FROM (
SELECT *, ROW_NUMBER()OVER(PARTITION BY Last_Name, First_Name ORDER BY DATE DESC) as ROW_NUM
FROM TABLE
) AS T
WHERE ROW_NUM = 1
Then you filter for ROW_NUM = 1.
However, I noticed that there are a couple with the same date and you want both. In this caseyou'd want to use RANK - which allows for ties so there may be multiple records with the same date that you want to capture.
SELECT * FROM (
SELECT *, RANK()OVER(PARTITION BY Last_Name, First_Name ORDER BY DATE DESC) as ROW_NUM
FROM TABLE
) AS T
WHERE ROW_NUM = 1

proc sql function to find mulitple LIKE matches?

I'm having trouble with a LIKE function in proc sql.
PROC SQL;
CREATE TABLE NAMES_IDS AS
SELECT DISTINCT
T1.*
,T2.NAMES
,T2.NAME_ID
FROM WORK.table1 T1
LEFT JOIN data.table2 T2 ON T2.NAMES like T1.NAMES1
;QUIT;
I have several names in t2, lets say for example theres John 1, John 2, John 3, John 4, etc and in t1.Names1 there is %John%
proc sql is just pulling in the first match, John 1 and its associated ID, and applying it to all the data in T1, instead of duplicated a match for all matching names (this is what I want to achieve).
So the end table would have something like
COLUMN A COLUMN B
John John 1
John John 2
John John 3
John John 4
But instead, what I get is:
COLUMN A COLUMN B
John John 1
John John 1
John John 1
John John 1
Hopefully this makes some sort of sense...
I think I figured it out, I added TRIM to my code and I guess there may have been some erroneous spaces somewhere because that seems to fix my issue. Thanks for your responses!

Joining two tables without duplicating

I have tables like this
Table 1 :
ID NAME
001 John
Table 2 :
ID NAME FAMILY
001 John Kate
001 John Jane
Table 3 :
ID NAME TRAINING
001 John ERP
001 John CCNA
001 John Java
I want to join these tables and show data like this :
Join Table :
ID NAME FAMILY TRAINING
001 John Kate ERP
001 John Jane CCNA
001 John Java
Can someone help me find a SQL statement so that I can get that result?
I Try using UNION like this
SELECT table1.ID, table1.name, table2.family, null as training
FROM table1 INNER JOIN table2 ON table1.ID = table2.ID
UNION
SELECT table1.ID, table1.name, null as family, table3.training
FROM table1 INNER JOIN table2 ON table1.ID = table3.ID
i got result like this :
ID NAME FAMILY TRAINING
001 John Kate NULL
001 John Jane NULL
001 John NULL Java
001 John NULL CCNA
001 John NULL ERP
but, i want to got result like this
ID NAME FAMILY TRAINING
001 John Kate ERP
001 John Jane CCNA
001 John NULL Java
so, anyone here can help me to solve this problem?
Don't think this can be done in a generic way. There is no way to connect Training to Family, there is no connection between the 2. Kate has nothing to do with ERP, could just as easily be CCNA or Java. Therefor, you will always get 6 results: John-Kate-3 Trainings, John-Jane-3 Trainings. (which is the correct result, logically speaking)
If you really want the result you mentioned, and I can't think of a reason why you would, you'd have to write a non-generic query. This would probably be along the lines of:
First select John, Kate and a (random?) training (top 1, or something, I'm not familiar with firebird)
Then select the same for Jane
Finally select John, NULL and the left-over training.
Like I said, this would be a non-generic query where you use the values "Kate" and "Jane" in the where clause(s).
If I where you, I'd have some deep thoughts about the whole set-up, and what you're trying to accomplish. You are trying to use SQL to do something it was never meant to do, in fact, it's the opposite of what SQL was meant to do.

Rollup a table eliminating null values

I'm pretty sure this should be easy, I just don't know what function or whatever I need to get it done. I've got a table that has the number of hours worked in a day, # of documents reviewed, and the date they were reviewed.
I've been able to combine and pivot this out into a nice report of the person and the # of hours or docs. However, it's got null values throughout.
First Last 11/30/2013 12/1/2013 12/2/2013
John Doe 11 NULL NULL
John Doe NULL 12 NULL
John Doe NULL NULL 8
John Doe NULL NULL NULL
I need it to look like this
FirstName LastName 11/30/2013 12/1/2013 12/2/2013
John Doe 11 12 8
Jane Smith 13 5 8
Figured it out, why it took me so long... I'm going to blame it on it being late...
Select Employee_ID
,SUM(#Temp3.[1])
,SUM(#Temp3.[2])
,SUM(#Temp3.[4])
,SUM(#Temp3.[5])
,SUM(#Temp3.[6])
,SUM(#Temp3.[7])
From #Temp3
Group By Employee_ID