purchased a movie earlier than Gladiator date SQL SERVER - sql

I needed guidance and help with a question I have never done in SQL SERVER.
I have this data:
Cust_Nr Date FilmName
157649306 20150430 Inside Llewyn Davis
158470722 20150504 Nick Cave: 20,000 Days On Earth
158467945 20150504 Out Of The Furnace
158470531 20150504 FilmA
157649306 20150510 Gladiator
158470722 20150515 Gladiator
The customer number :158470722 has bought two movies,1):Inside Llewyn Davis and 2) Gladiator on different dates. What I am trying to do in SQL SERVER is to this:
Cust_Nr Date FilmName Before Gladiator Purchase
157649306 20150430 Inside Llewyn Davis 1
158470722 20150504 Nick Cave: 20,000 Days On Earth 1
158467945 20150504 Out Of The Furnace 0
158470531 20150504 FilmA 0
157649306 20150510 Gladiator 0
158470722 20150515 Gladiator 0
If we look at the dates for the customer nr:157649306, he purchased a movie on a date ,20150430, and purchased Gladiator on the 20150510. How can I create a column like the one above to show if a customer has purchased a movie on a date earlier than the gladiator date?

You can do this with conditional aggregation and window/analytic functionality:
SELECT *,CASE WHEN [Date] < MIN(CASE WHEN FilmName = 'Gladiator'
THEN [Date]
END) OVER(PARTITION BY Cust_Nr)
THEN 1
ELSE 0
END AS Before_Gladiator
FROM Table1
Demo: SQL Fiddle

You need agregation and details in the same query, so use a Windowed Aggregate Function:
case
when Date < min(case when FilmName = 'Gladiator' then Date end)
over (partition by Cust_Nr)
then 1
else 0
end

You could join the table with a query on the gladiator movie:
SELECT t.*,
CASE WHEN g_date IS NULL OR t.[date] > g_date THEN 1 ELSE 0 END
FROM mytable t
LEFT JOIN (SELECT [date] AS g_date, Cust_Nr
FROM mytable
WHERE FileName = 'Gladiator') g ON t.Cust_Nr = g.Cust_Nr

Related

Datediff on 2 rows of a table with a condition

My data looks like the following
TicketID OwnedbyTeamT Createddate ClosedDate
1234 A
1234 A 01/01/2019 01/05/2019
1234 A 10/05/2018 10/07/2018
1234 B 10/04/2019 10/08/2018
1234 finance 11/01/2018 11/11/2018
1234 B 12/02/2018
Now, I want to calculate the datediff between the closeddates for teams A, and B, if the max closeddate for team A is greater than max closeddate team B. If it is smaller or null I don't want to see them. So, for example,I want to see only one record like this :
TicketID (Datediff)result-days
1234 86
and for another tickets, display the info. For example, if the conditions aren't met then:
TicketID (Datediff)result-days
2456 -1111111
Data sample for 2456:
TicketID OwnedbyTeamT Createddate ClosedDate
2456 A
2456 A 10/01/2019 10/05/2019
2456 B 08/05/2018 08/07/2018
2456 B 06/04/2019 06/08/2018
2456 finance 11/01/2018 11/11/2018
2456 B 12/02/2018
I want to see the difference in days between 01/05/2019 for team A, and
10/08/2018 for team B.
Here is the query that I wrote, however, all I see is -1111111, any help please?:
SELECT A.incidentid,
( CASE
WHEN Max(B.[build validation]) <> 'No data'
AND Max(A.crfs) <> 'No data'
AND Max(B.[build validation]) < Max(A.crfs) THEN
Datediff(day, Max(B.[build validation]), Max(A.crfs))
ELSE -1111111
END ) AS 'Days-CRF-diff'
FROM (SELECT DISTINCT incidentid,
Iif(( ownedbyteam = 'B'
AND titlet LIKE '%Build validation%' ), Cast(
closeddatetimet AS NVARCHAR(255)), 'No data') AS
'Build Validation'
FROM incidentticketspecifics) B
INNER JOIN (SELECT incidentid,
Iif(( ownedbyteamt = 'B'
OR ownedbyteamt =
'Finance' ),
Cast(
closeddatetimet AS NVARCHAR(255)), 'No data') AS
'CRFS'
FROM incidentticketspecifics
GROUP BY incidentid,
ownedbyteamt,
closeddatetimet) CRF
ON A.incidentid = B.incidentid
GROUP BY A.incidentid
I hope the following answer will be of help.
With two subqueries for the two teams (A and B), the max date for every Ticket is brought. A left join between these two tables is performed to have these information in the same row in order to perform DATEDIFF. The last WHERE clause keeps the row with the dates greater for A team than team B.
Please change [YourDB] and [MytableName] in the following code with your names.
--Select the items to be viewed in the final view along with the difference in days
SELECT A.[TicketID],A.[OwnedbyTeamT], A.[Max_DateA],B.[OwnedbyTeamT], B.[Max_DateB], DATEDIFF(dd,B.[Max_DateB],A.[Max_DateA]) AS My_Diff
FROM
(
--The following subquery creates a table A with the max date for every project for team A
SELECT [TicketID]
,[OwnedbyTeamT]
,MAX([ClosedDate]) AS Max_DateA
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
HAVING [OwnedbyTeamT]='A')A
--A join between view A and B to bring the max dates for every project
LEFT JOIN (
--The max date for every project for team B
SELECT [TicketID]
,[OwnedbyTeamT]
,MAX([ClosedDate]) AS Max_DateB
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
HAVING [OwnedbyTeamT]='B')B
ON A.[TicketID]=B.[TicketID]
--Fill out the rows on the max dates for the teams
WHERE A.Max_DateA>B.Max_DateB
You might be able to do with a PIVOT. I am leaving a working example.
SELECT [TicketID], "A", "B", DATEDIFF(dd,"B","A") AS My_Date_Diff
FROM
(
SELECT [TicketID],[OwnedbyTeamT],MAX([ClosedDate]) AS My_Max
FROM [YourDB].[dbo].[MytableName]
GROUP BY [TicketID],[OwnedbyTeamT]
)Temp
PIVOT
(
MAX(My_Max)
FOR Temp.[OwnedbyTeamT] in ("A","B")
)PIV
WHERE "A">"B"
Your sample query is quite complicated and has conditions not mentioned in the text. It doesn't really help.
I want to calculate the datediff between the closeddates for teams A, and B, if the max closeddate for team A is greater than max closeddate team B. If it is smaller or null I don't want to see them.
I think you want this per TicketId. You can do this using conditional aggregation:
SELECT TicketId,
DATEDIFF(day,
MAX(CASE WHEN OwnedbyTeamT = 'B' THEN ClosedDate END),
MAX(CASE WHEN OwnedbyTeamT = 'A' THEN ClosedDate END) as diff
)
FROM incidentticketspecifics its
GROUP BY TicketId
HAVING MAX(CASE WHEN OwnedbyTeamT = 'A' THEN ClosedDate END) >
MAX(CASE WHEN OwnedbyTeamT = 'B' THEN ClosedDate END)

Using two Select statements in one query to bring back desired data set

Please help in correcting this query.
I am trying to bring back the TRADE_AMT for the last week (w1) and then for the year (YTD). But the query keeps failing, I know there is a simpler solution but that is not I am looking for as I would like to learn this idea of using multiple select statements to bring back one data set as per the very first Select statement.
Also, I would like to group by login IDs but I know I can have only one from statement.
Here is my query:
SELECT login, W1.TRADE_AMT, YTD.TRADE_AMT
FROM
(SELECT sum(TRADE_AMT) FROM CORPS
WHERE DATE > 20180903 AND DATE_ID <= 20180910
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12') ) AS W1
UNION ALL
(SELECT sum(TRADE_AMT) FROM CORPS
WHERE DATE > 20180101 AND DATE_ID < 20180911
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12') ) AS YTD
GROUP BY login
Sample Date From Corps Table:
Login Trade_AMT Date Rating
ITI1 100 20180509 High
RAB0 150 20180910 High
RR12 25 20180104 High
YTRT 100 20180225 Low
ACE1 123 20180908 Low
ITI1 354 20180903 Low
RAB0 254 20180331 High
RR12 245 20180314 High
RR12 5236 20180505 High
Desired Result:
Login W1_Volume YTD_Volume
ITI1 100 2000
RAB0 150 2500
RR12 25 3000
could be using an inner join on subquery group by login
SELECT W1.login, W1.TRADE_AMT, YTD.TRADE_AMT
FROM
(SELECT login, sum(TRADE_AMT) AS TRADE_AMT FROM CORPS
WHERE DATE > 20180903 AND DATE_ID <= 20180910
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12')
GROUP BY LOGIN) AS W1
LEFT JOIN (
SELECT login, sum(TRADE_AMT) AS TRADE_AMT FROM CORPS
WHERE DATE > 20180101 AND DATE_ID < 20180911
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12')
GROUP BY LOGIN ) AS YTD ON YTD.LOGIN = W1.LOGIN
left join show also not matching login values but you can use inner join if you need oly matching login between week and year
According to sample i got that you need min() of TRADE_AMT for 1st sub-query but not got the 2nd sub-query aggregate function properly
SELECT login, W1.TRADE_AMT, YTD.TRADE_AMT
FROM
(SELECT login,min(TRADE_AMT) as TRADE_AMT FROM CORPS
WHERE DATE > '20180903' AND DATE_ID <= '20180910'
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12')
group by login) AS W1
join
(SELECT login, sum(TRADE_AMT) as TRADE_AMT FROM CORPS
WHERE DATE > '20180101' AND DATE_ID < '20180911'
AND REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12')
group by login
) AS YTD
on W1.login=YTD.login
Simply use case expressions to do conditional aggregation:
SELECT login,
sum(case when DATE > 20180903 AND DATE_ID <= 20180910 then TRADE_AMT end) W1_Volume,
sum(case when DATE > 20180101 AND DATE_ID < 20180911 then TRADE_AMT end) YTD_Volume
FROM CORPS
WHERE REGION = 'London'
AND Rating = 'High'
AND LOGIN IN ('ITI1','RAB0','RR12')
GROUP BY login
Optionally you can put back a date condition to the WHERE clause to speed things up:
AND DATE > 20180101 AND DATE_ID < 20180911
Bottom line is your outer query can't be selective (W1.something, YTD.something), from the inner queries when you put them together with a union. They get melded into a single result set. When you union, you have to leave "clues" in the result set to figure why the rows are interesting:
SELECT [login], TRADE_AMT, amt_type
FROM
(
SELECT
[login], sum(TRADE_AMT), 'week' as amt_type
FROM
CORPS
WHERE
DATE > 20180903 AND DATE_ID <= 20180910
AND REGION = 'London'
AND Rating = 'High'
AND [LOGIN] IN ('ITI1','RAB0','RR12')
group by
[login]
UNION ALL
SELECT
[login], sum(TRADE_AMT), 'ytd' as amt_type
FROM
CORPS
WHERE
DATE > 20180101 AND DATE_ID < 20180911
AND REGION = 'London'
AND Rating = 'High'
AND [LOGIN] IN ('ITI1','RAB0','RR12')
group by
[login]
)
...where the amt_type indicates whether it was from the ytd query or the week query.
That's the issue with union queries. You can pivot the result set, but that's unnecessary...unless you just need the results in a particular format. It depends on the code consuming the result set.
(Also - LOGIN is a reserved word...probably ought to bracket it where you don't mean the reserved word)
You can get your result sets on one-line-per-login with a join (rather than a union), as per scaisEdge answer, but I assumed you were trying to figure out the union approach.

SQL: calculate value based on two different conditions

Below is my table schema:- Appointments
--------------------------------------
| schID | appointment_date | amount | location |
--------------------------------------
I want to fire a single query where I can get the sum of amount, total appointment_date this year i.e 2016 and remaining appointment_date this year i.e 2016.
So I wrote the below query to calculate the above fields:-
SELECT sum(a.amount) as total,
count(distinct a.appointment_date) as total_appointment,
count(distinct a2.appointment_date) as remaining appointments
from Appointments a
LEFT JOIN Appointments a2 ON a.schID = a2.schID
WHERE a2.appointment_date > GETDATE() AND year(a.appointment_date) = 2016
group by a.location
The above query doesnt return value as per requirement :(
The database belongs to SQL Server.
You can use conditional aggregation for this:
SELECT sum(amount) as total,
count(appointment_date) as total_appointment,
count(DISTINCT CASE
WHEN appointment_date > GETDATE() AND YEAR(appointment_date) = 2016
THEN DATE(appointment_date)
END) as remaining appointments
from Appointments a
group by a.location
You shouldn't need a join for this type of query:
SELECT sum(a.amount) as total, count(a.appointment_date) as total_appointment,
sum(case when a.appointment_date > getdate() then 1 else 0
end) as remaining appointments
from Appointments a
where year(a.appointment_date) = year(GETDATE() );
If you need the breakdown by location, then include location in both the select and group by clauses.

Bring through a newly created calculated column in another query

I have 2 separate queries below which run correctly.Now I've created a calculated column to provide a count of working days by YMs and would like to bring this through to query1(the join would be query1.Period = query2.Yms)
please see the query and outputs below.
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName
FROM metrics.dbo.vw_KPI_001_Invoice
select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs
Query 1
Client ClientGroup Type Value Period PeriodName PeriodNumber ClientName
0LG0 KarroFoods Stock 5691.68 201506 Week 06 2015 35 Karro Foods Scunthorpe
Query 2
YMs (No column name)
201401 23
Would the following work:
SELECT Client, ClientGroup, Type, Value, Period, PeriodName, PeriodNumber, ClientName, cnt
FROM metrics.dbo.vw_KPI_001_Invoice q1
INNER JOIN (select YMs,sum(case when IsWorkDay = 'X' then 1 else 0 end) as cnt from IESAONLINE.Dbo.DS_Dates
where Year > '2013'
group by YMs ) q2 ON q1.Period = q2.YMs
If a value isn't always available then you might consider changing the INNER JOIN to an OUTER JOIN.

sql combining two queries and truncating date

I am trying to truncate dates to only get year/month as opposed to the form they are in which is year/month/day.time
What I want to do is count all of the cars that sold each month and all of the suvs that sold each month, having something like:
// counts cars
select SellDate, count(*)
from category
where machineIdentification = 1
GROUP BY SellDate
// counts suv's
select SellDate, count(*)
from category
where machineIdentification = 2
GROUP BY SellDate
Separately running each query gives me a list of dates (y/m/d/time to the second) and the number 1 because only 1 car or suv sold that exact time, however I am trying to group by SellDate and truncate the date so it only shows me the total numbers each month.
what I am trying to do is combine the queries and end up with values like so:
2009-01 23 10
2009-02 13 14
2009-03 29 7
With the first column being the year.month, the second being # of cars sold and the third being # of suv's sold
select
date(SellDate, 'start of month'),
SUM (CASE machineIdentification = 1 THEN 1 ELSE 0 END) AS carcount ,
SUM (CASE machineIdentification = 2 THEN 1 ELSE 0 END) AS suvcount
from category
where machineIdentification IN (1, 2 )
GROUP BY date(SellDate, 'start of month')
I'd concatenate the year/month in the client code so you can have "July 2010" for example
(I can't test in SQLLite, sorry, but this should be close except for output year/month format)
It could involve a union in a subquery and a format on the date, reformatted for SQLLite:
SELECT SellDate, COUNT(CARS) AS Cars, COUNT(SUVS) AS SUVS
FROM
(SELECT STRFTIME('%Y-%m',SellDate) AS SellDate,
MachineIdentification AS CARS, null AS SUVS
FROM Category
where machineIdentification = 1
UNION
SELECT STRFTIME('%Y-%m',SellDate) AS SellDate,
null AS CARS, MachineIdentification AS SUVS
FROM Category
where machineIdentification = 2
)
GROUP BY SellDate