Return first date and previous dates - sql

There is a custid with 3 dates .
I want to return first date and then its previous date .
data should look like:
custid first previous
11 2019-06-10 2019-06-15
11 2019-06-10 2019-07-10
I have done it but I'm not able to put it in 2nd row.
SELECT A.PersonID ,min(a.date) as first,b.date as previous,c.date as previous from Persons as a
INNER JOIN (select PersonID ,date from Persons) b
on a.PersonID
=b.PersonID AND
a.date<
b.date
INNER JOIN (select PersonID ,date from Persons) c
on b.PersonID=
c.PersonID
AND b.date<
c.date
Output which I'm getting:
personid first previous previous
11 2019-06-10 2019-06-15 2019-07-10
I want it to look like:
custid first previous
11 2019-06-10 2019-06-15
11 2019-06-10 2019-07-10

You don't need to add the 3rd inner join table. Since your using min() with other columns, this should be accompanied by Group By.
select
a.PersonID as custid,
min(a.date) as first,
b.date as previous
from
Persons as a
inner join Persons b on a.PersonID = b.PersonID and b.date > a.date
group by a.PersonID, b.date

Related

SQL join type to have as many rows as each date for each customer

I have these two tables
date
2017-1
2017-2
2017-3
2017-4
2017-5
2017-6
and
date
customer
no_orders
city_code
2017-1
156
1
DNZ
2017-3
156
5
LON
2017-5
156
4
DNZ
2017-6
156
2
YQB
How can I join these two tables to have one row for each customer for all the dates same as below?
If on a date, the customer has no order, its no_order should be 0 and its city_code should be the city_code of the previous date.
date
customer
no_orders
city_code_2
2017-1
156
1
DNZ
2017-2
156
0
DNZ
2017-3
156
5
LON
2017-4
156
0
LON
2017-5
156
4
DNZ
2017-6
156
2
YQB
This code by #Tim Biegeleisen resolved part 1 of my question but now I want to handle both parts with each other.
SELECT d.date, c.customer, COALESCE(t.no_orders, 0) AS no_orders
FROM dates d
CROSS JOIN (SELECT DISTINCT customer FROM customers) c
LEFT JOIN customers t
ON t.date = d.date AND
t.customer = c.customer
ORDER BY c.customer, d.date;
We can use the following calendar table approach:
SELECT d.date, c.customer, COALESCE(t.no_orders, 0) AS no_orders
FROM dates d
CROSS JOIN (SELECT DISTINCT customer FROM customers) c
LEFT JOIN customers t
ON t.date = d.date AND
t.customer = c.customer
ORDER BY c.customer, d.date;
This assumes that the first table is called dates and the second table customers. The query works by using a cross join to generate a set of all dates and customers. We then left join to the second table to bring in the number of orders for a given customer on a given day. Absent number of orders are reported as zero.

How to filter for minimum date and remove duplicate dates in joined table?

I am attempting to join three tables with the parent table to get an output of customer id, visit id, and visit date where the oldest date is selected if more than one date. All four tables contain the cust_id, visit_id, and visit_date variables, but visit_id is the linking variable. I named the four tables a, b, c, and d to simplify the code below (a is the parent table).
My current code below gets me closer to my desired output, but I'm not sure how to get one visit_date column with the oldest date by visit_id and am unsure on how to remove duplicates. Any help will be sincerely appreciated, and please let me know if I can clarify anything!
SELECT
a.cust_id,
a.visit_id,
a.visit_date,
b.visit_date,
c.visit_date,
d.visit_date
FROM a
LEFT JOIN b
ON a.visit_id = b.visit_id
LEFT JOIN c
ON a.visit_id = c.visit_id
LEFT JOIN d
ON a.visit_id = d.visit_id
WHERE a.visit_date IS NOT NULL
OR b.visit_date IS NOT NULL
OR c.visit_date IS NOT NULL
OR d.visit_date IS NOT NULL;
My current output looks like this:
cust_id
visit_id
visit_date
visit_date
visit_date
visit_date
001
001
2013-05-23
002
002
2013-06-03
2013-05-27
003
003
2013-06-05
2013-06-05
2013-06-05
003
004
2013-07-09
2013-07-09
2013-07-06
My desired output looks like this:
cust_id
visit_id
visit_date
001
001
2013-05-23
002
002
2013-05-27
003
003
2013-06-05
003
004
2013-07-06
You could use the scalar LEAST function:
SELECT
a.cust_id,
a.visit_id,
LEAST(a.visit_date, b.visit_date, c.visit_date, d.visit_date) AS visit_date
FROM a
LEFT JOIN b
ON a.visit_id = b.visit_id
LEFT JOIN c
ON a.visit_id = c.visit_id
LEFT JOIN d
ON a.visit_id = d.visit_id
WHERE
a.visit_date IS NOT NULL OR
b.visit_date IS NOT NULL OR
c.visit_date IS NOT NULL OR
d.visit_date IS NOT NULL;

Joining multiple tables with same identifier & pulling in a field based on shared identifier

The context: a health care clinic has 2 tables: one on patient visits, and one on patient appointments. They are not 1:1; it is possible to have an appointment without a visit, or to have a visit without an appointment. The identifier for both tables is the encounter ID, enc_ID. I'm trying to outer join these tables together and to pull in patient names.
A boiled-down example of the visit table (V):
enc_ID Visit_date Patient_ID
1 2018-06-01 10
2 2018-06-02 11
And the appointment data (A):
enc_ID Appointment_time Patient_ID
1 2018-06-01 13:00 10
3 2018-06-03 14:00 12
Outer-joining these on visit_ID would produce something like:
enc_ID V.Visit_date A.Appointment_time V.Patient_ID A.Patient_ID
1 2018-06-01 2018-06-01 13:00 10 10
2 2018-06-02 NULL 11 NULL
3 NULL 2018-06-03 14:00 NULL 12
Say I want to basically combine V.Patient_ID and A.Patient_ID, and pull in patient name from another table (P), joined on Patient_ID. The desired output:
enc_ID V.Visit_date A.Appointment_time Patient_ID Patient_Name
1 2018-06-01 2018-06-01 13:00 10 Patient A
2 2018-06-02 NULL 11 Patient B
3 NULL 2018-06-03 14:00 13 Patient C
How might this be accomplished? I'm probably missing something obvious, but I don't see how I can join in P.Patient_Name without having to join it to either V.Patient_ID or A.Patient_ID, either of which would result in null patient names.
Thanks in advance!
As long as enc_ID in both tables are not nullable, you can combine those fields with a COALESCE:
SELECT
COALESCE(V.Patient_ID, A.Patient_ID) AS enc_ID,
V.Visit_date,
A.Appointment_time,
COALESCE(V.Patient_ID, A.Patient_ID) AS Patient_ID,
P.Patient_Name
FROM V
FULL JOIN A ON V.enc_ID = A.enc_ID
INNER JOIN P
ON P.Patient_ID = V.Patient_ID
OR P.Patient_ID = A.Patient_ID
-- ON P.Patient_ID = COALESCE(V.Patient_ID, A.Patient_ID) also works
You can use ISNULL to join table P.
...(Your outer join query)
LEFT JOIN P
ON P.Patient_ID = ISNULL(V.Patient_ID, A.PatientID)

Left join not producing correct result

I want to return all people regardless of whether they have a sale on any given day. My initial response to solve this would be
SELECT
P.[Name], P.[id],
F.[DATE], F.[Figure], F.[id]
FROM
Person P
LEFT JOIN
Figure F ON P.id = F.id
An example of the result for this is
Name id DATE Figure
--------------------------------------------
Tom 1 2017-09-27 15
Fred 2 2017-09-27 20
Jane 3 2017-09-25 0
Ben 4 2017-09-25 0
Now as soon as I limit the date to today's date, I get nothing.
SELECT
P.[Name], P.[id],
F.[DATE], F.[Figure], F.[id]
FROM
Person P
LEFT JOIN
Figure F ON P.id = F.id
WHERE
F.Date = GETDATE()
I understand this is probably because there is no one with today's date attached to them but how do I still display all of the people even if they had nothing for today? I thought that a left join would accomplish this but it doesn't.
My desired results would be :
Name id DATE Figure
--------------------------------------------
Tom 1 2017-10-02 0
Fred 2 2017-10-02 0
Jane 3 2017-10-02 0
Ben 4 2017-10-02 0
There are no keys in the tables so I feel as though that might be why the left join isn't working as I expected but has anyone got any ideas how I can get the desired result?
First, the condition needs to go in the ON clause rather than the WHERE clause, because it is on the second table.
Second, getdate() -- despite its name -- has a time component. So, convert it to a date:
FROM Person P LEFT JOIN
Figure F
ON P.id = F.id AND F.Date = CAST(getdate() as DATE)
Put your query in a cte and then pull from it to achieve your desired results:
;with cte_example
as
(SELECT
P.[Name],
P.[id],
F.[DATE], F.[Figure], F.[id]
FROM
Person P
LEFT JOIN Figure F
ON P.id = F.id)
select Name
,id
,cast(getdate() as date) as date
,case when date = convert(date, getdate()) then Figure else 0 end as Figure
from cte_example
I made a rextester example so you could see

SQL Server joining two tables, order by and display one record

I am having trouble with a SQL Server statement. The perfect scenario is the order and another table (jobs) by date created then display the contact information in descending order. Currently I can get the script to show all records, however if the user has more than one job then they are displayed more than once.
SELECT
c.*,
p.date_created
FROM
[db].[dbo].[Contact] AS c
JOIN
[db].[dbo].[job] AS p ON p.contact_id = c.contact_id
UNION
SELECT
*,
0 as date_created
FROM
[db].[dbo].[Contact]
ORDER BY
p.date_created DESC
The output
contact_id| date_created | contact_name
1 | 8/29/2016 1:07:18 PM | sam
1 | 8/26/2016 1:04:01 PM | sam
14 | 8/24/2016 5:07:22 PM | steve
The final output should just show the newest date created and for one user. Help is much appreciated.
The column in union select must match for number and type so convert 0 in a proper date
SELECT
c.contact_id
,max(p.date_created)
,c. contact_name
FROM [db].[dbo].[Contact] AS c
JOIN [db].[dbo].[job] AS p
ON p.contact_id = c.contact_id
GROUP BY c.contact_id,c. contact_name
union
select
c.contact_id
, convert(datetime, '01/01/1070', 101) as date_created
, c. contact_name
from [db].[dbo].[Contact]
ORDER BY p.date_created desc`
The result you need anyway should be obtainable with only
SELECT
c.contact_id
,max(p.date_created) as max_date_created
,c. contact_name
FROM [db].[dbo].[Contact] AS c
LEFT JOIN [db].[dbo].[job] AS p
ON p.contact_id = c.contact_id
GROUP BY c.contact_id,c. contact_name
ORDER BY c.contact_id,c. contact_name, max_date_created