Combining the results of two JOINS in SQL - sql

Tickets last 24 hours and can be either 'Child', 'Adult' or 'Teen'. Essentially, a ticket can be 'ConnectedTo' a number of movies. Child tickets for example will be connected to movies with a age rating of PG or below, while Adult tickets will be connected to every single movie.
The below returns info on all the tickets purchased for movies from the previous month:
SELECT *
FROM
[Test_DB].[dbo].[Tickets]
INNER JOIN
[Test_DB].[dbo].[Movies]
ON
[Test_DB].[dbo].[Tickets].[ConnectedTo] = [Test_DB].[dbo].[Movies].[MovieID]
WHERE
[Test_DB].[dbo].[Tickets].[DateEntered] >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-1, 0) AND [Test_DB].[dbo].[Tickets].[DateEntered] <= DATEADD(month, DATEDIFF(month, 0, GETDATE()), -1)
Each ticket can have any number of notes attached to it. For example, if a special discount was given to a ticket holder, a note will be created about that. Similiarly, if a ticket is exchanged for another or refunded, a note will be created.
The below will return all the notes for a given Ticket based on the TicketID:
SELECT *
FROM
[Test_DB].[dbo].[Tickets]
JOIN [Test_DB].[dbo].[Notes]
ON [Test_DB].[dbo].[Tickets].[TicketID] = [Test_DB].[dbo].[Notes].[ConnectedTo]
WHERE TicketId = 64903
My question is, is there a way to combine the two? For example, the first bit of SQL could return 5 tickets, each with a different TicketID. Based on that, I want to make use of my second SQL to return all of the notes for those 5 tickets.
I was thinking of using UNION to combine the two selects... Though my brain keeps telling me that I need to JOIN the two pieces of SQL on the TicketId's, however every time I try to it comes out wrong. Any help would greatly be appreciated! Thanks.

This should work
SELECT [Test_DB].[dbo].[Tickets].*, [Test_DB].[dbo].[Notes].*
FROM [Test_DB].[dbo].[Tickets]
INNER JOIN [Test_DB].[dbo].[Movies]
ON
[Test_DB].[dbo].[Tickets].[ConnectedTo] = [Test_DB].[dbo].[Movies].[MovieID]
INNER JOIN [Test_DB].[dbo].[Notes]
ON [Test_DB].[dbo].[Tickets].[TicketID] = [Test_DB].[dbo].[Notes].[ConnectedTo]
WHERE [Test_DB].[dbo].[Tickets].[DateEntered] >= DATEADD(month, DATEDIFF(month, 0, GETDATE())-1, 0)
AND [Test_DB].[dbo].[Tickets].[DateEntered] <= DATEADD(month, DATEDIFF(month, 0, GETDATE()), -1)

I imagine that "notes" could be optional. If so, then you will want a left join rather than an inner join. Also, the use of aliases and eliminating the unnecessary square brackets would make your query easier to read:
SELECT *
FROM Test_DB.dbo.Tickets t INNER JOIN
Test_DB.dbo.Movies m
ON t.ConnectedTo = m.MovieID LEFT JOIN
Test_DB.dbo.Notes n
ON t.TicketID = n.ConnectedTo
WHERE t.DateEntered >= DATEADD(month, DATEDIFF(month, 0, GETDATE()) -1, 0) AND
t.DateEntered <= DATEADD(month, DATEDIFF(month, 0, GETDATE()), -1);
Note (no pun intended): if a ticket has multiple notes, then you will get multiple rows in the output.

Related

How to Combine Two Columns from Two different Queries with Different Datatypes?

I'm trying to ultimately get a sum of two columns. The issue is that the sum is made up from two different tables. Basically it's tbl1-col1 + tabl2-col1.
I'm attempting a UNION ALL, but the issue is that for me to pull the right data from both queries to even get the right data in the col1's, I need to SELECT different parameters for both queries.
Obviously I'm working with different datatypes and header titles, so that UNION isn't going to work the way I want it to.
-------------------------------query 1------------------------------------------------
SELECT
RECEIVABLE_LINE.AMOUNT AS Total,
RECEIVABLE_LINE.INVOICE_ID,
RECEIVABLE_LINE.LINE_NO,
RECEIVABLE_LINE.GL_ACCOUNT_ID,
RECEIVABLE.INVOICE_DATE,
RECEIVABLE.TYPE
FROM RECEIVABLE_LINE INNER JOIN RECEIVABLE ON RECEIVABLE_LINE.[INVOICE_ID] = RECEIVABLE.[INVOICE_ID]
WHERE RECEIVABLE_LINE.GL_ACCOUNT_ID LIKE '4%'
AND RECEIVABLE.INVOICE_DATE >= DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE()), 0)
AND RECEIVABLE.INVOICE_DATE < DATEADD(MONTH, DATEDIFF(MONTH, 0, GETDATE())+1, 0)
-------------------------------query 2------------------------------------------------
SELECT
SUM(SHIPPER_LINE.USER_SHIPPED_QTY*CUST_ORDER_LINE.UNIT_PRICE) AS 'Total',
SHIPPER_LINE.USER_SHIPPED_QTY,
CUST_ORDER_LINE.UNIT_PRICE,
SHIPPER.INVOICED_DATE,
SHIPPER.SHIPPED_DATE
--SUM(isnull(CAST('Total' AS decimal),0)) as 'Total of all totals'
FROM SHIPPER_LINE INNER JOIN SHIPPER ON SHIPPER_LINE.PACKLIST_ID = SHIPPER.PACKLIST_ID
LEFT JOIN CUST_ORDER_LINE ON SHIPPER_LINE.CUST_ORDER_LINE_NO = CUST_ORDER_LINE.LINE_NO AND SHIPPER_LINE.CUST_ORDER_ID = CUST_ORDER_LINE.CUST_ORDER_ID
WHERE SHIPPER.INVOICED_DATE Is Null
AND SHIPPER.SHIPPED_DATE BETWEEN '2020-09-01' AND '2020-09-10'
GROUP BY SHIPPER_LINE.USER_SHIPPED_QTY, CUST_ORDER_LINE.UNIT_PRICE, SHIPPER.INVOICED_DATE, SHIPPER.SHIPPED_DATE
ORDER BY SHIPPER.INVOICED_DATE
What are my options at this point?

a query displaying 0 instead of not showing

the following query is displaying the result i want except i want it to show 0 for each month with non production.
SELECT
DATENAME(MONTH, DATEADD(M, MONTH(PolicyDetails.IssuedDate), - 1)) AS Month,
SUM(PolicyDetails.Premium) AS TotalProduction,
DATENAME(YEAR, PolicyDetails.IssuedDate) AS Year
FROM PolicyDetails INNER JOIN Clients
ON PolicyDetails.ClientId = Clients.ClientId
WHERE (Clients.Username = #Username)
GROUP BY MONTH(PolicyDetails.IssuedDate), DATENAME(YEAR, PolicyDetails.IssuedDate)
Month Total Production -$$
2019 - August 30.00
2019 - October 45.00
in this table i want to show "2019 - September" with Total Production = 0 instead of displaying nothing. How ??
If you want to show all months in the data, probably the simplest method is to use conditional aggregation. Your calculation of the month seems awkward. You seem to want the previous month, so:
SELECT DATENAME(YEAR, pd.IssuedDate) AS Year,
DATENAME(MONTH, DATEADD(MONTH, -1, pd.IssuedDate)) AS Month,
SUM(CASE WHEN c.Username = #Username THEN pd.Premium ELSE 0 END) AS TotalProduction
FROM PolicyDetails pd INNER JOIN
Clients c
ON pd.ClientId = c.ClientId
GROUP BY DATENAME(YEAR, pd.IssuedDate), DATENAME(MONTH, DATEADD(MONTH, -1, pd.IssuedDate))
ORDER BY MIN(pd.IssuedDate)
This assumes that you have at least one row per month in the data.
Otherwise, the canonical approach is to generate the months you want (using a derived table or recursive CTE or calendar table). Your month arithmetic is a bit awkward for that solution. It would look like:
SELECT YEAR(DATEADD(MONTH, -1, months.mstart)),
MONTH(DATEADD(MONTH, -1, months.mstart)),
COALESCE(SUM(pd.Premium), 0) AS TotalProduction
FROM (VALUES (CONVERT(DATE, '2019-08-01')),
(CONVERT(DATE, '2019-09-01')),
(CONVERT(DATE, '2019-10-01'))
) months(mstart) LEFT JOIN
PolicyDetails pd
ON pd.IssuedDate >= DATEADD(month, -1, months.mstart) AND
pd.IssuedDate < months.mstart LEFT JOIN
Clients c
ON pd.ClientId = c.ClientId AND
c.Username = #Username
GROUP BY YEAR(DATEADD(MONTH, -1, months.mstart)),
MONTH(DATEADD(MONTH, -1, months.mstart))
ORDER BY MIN(pd.IssuedDate)
I suppose that might be a usecase for SQL-IF.
Syntax as follows:
SELECT IF([condition], "YES", "NO");
In your case, try to combine that with your query.
Maybe like this:
SELECT IF([subquery > 0] AS X, X, 0);
If-Condition Like:
SELECT IF((SELECT COUNT(*) FROM PolicyDetails ) > 0, 1, 0);
But you will have to combine that output with your existing query posted above, to gain the output if the table is filled.

query to generate transactions from previous month

I need to write a query which when executed at the beginning of the current month must generate a report which contains total transactions made in the previous month and I have written the below query:
SELECT
l.state AS Province
,l.taxing_entity AS TaxJurisdiction
,COUNT(DISTINCT t.trans_id) AS TotalTransCount
FROM TRANSACTION AS t
LEFT OUTER JOIN location AS l
ON t.location_id = l.location_id
LEFT OUTER JOIN trans_line AS tl
ON t.trans_id = tl.trans_id
LEFT OUTER JOIN contract as c
ON t.contract_id = c.contract_id
WHERE
l.chain_id = 10
AND c.issuer_id IN (156967)
AND t.extra_5 BETWEEN LAST_DAY(TODAY - 2 units month) + 1 units day AND LAST_DAY(TODAY - 1 units month)
AND tl.cat NOT IN ('DEF','DEFD','DEFC')
GROUP BY l.state, l.taxing_entity, Province
ORDER BY l.state,l.taxing_entity
But this query throws an error "It is not possible to convert between the specified types. ". I tried changing the date range as below:
t.extra_5 >= DATEADD(MONTH, DATEDIFF(MONTH, 31, CURRENT_TIMESTAMP), 0) AND t.extra_5 < DATEADD(MONTH, DATEDIFF(MONTH, 0, CURRENT_TIMESTAMP), 0)
and
t.extra_5 > DateAdd(WEEK, -1, GETDATE()+1) and t.extra_5<=GETDATE()
But nothing has worked out so far. The current format for the column "extra_5" is as below:
Can someone please suggest a way to get the total transactions from previous month.

joining three select statements

I create reports in SQL Server Report Builder. I hope anyone can help me in this case. My query shows me an error if I add a third inner join
How can I add a third select statement?
You need to update the final GROUP BY clause. Including the full name in the SELECT clause requires the full name in the GROUP BY.
As a rule of thumb: When using GROUP BY every field used in the SELECT clause, that isn't combined with an aggregate function, must appear.
Select
SUM(cast(Units as int)) as CounterName,
left(Name,4) as Machine,
Name as WasteLabel
from
Trouble
inner join tsystem ON Trouble.systemid = tsystem.id
where
Name not in ('Aus', 'An', 'Produced')
and IntervalDateWeek >= dateadd(wk, datediff(wk, 0, getdate()) - 2, 0)
and IntervalDateWeek <= dateadd(wk, datediff(wk, 0, getdate())-1, 0)
and left(Name, 4) in (Select name from tSystem
where
ID in
(
Select
systemid
from
tsystemviewSystemwhere
WHERE
SystemViewID = 4)
)
group by
Name
I suspect your query could be improved. Adding clear sample data and expected output will help here.

Using sub-query to count specific rows

I have a query that I am using for a report. Each line is a row of data containing a medical history, the client_id is repeated for each medical history.
I'm grouping by client_id and summing their conditions but I want to use a sub-query to find any conditions that are above a preset score. My current query is giving me the total for the whole table, not just the specific client_id.
Can someone help me out? Thanks!
Here my query:
select
DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
(select count(hscore)
from amexmedscreen
where hscore >= '3.5')
from amexmedscreen
group by taken_on, client_id`
It should be sufficient to use CASE to get 1 for relevant rows, and sum those:
select
...
sum(hscore),
sum(CASE WHEN hscore >= 3.5 THEN 1 ELSE 0 END)
group by taken_on, client_id`
Your subquery is a separate query. It's not constrained by what's going on in the main query. You need to tell it to do the count only for the client_id of the current record in the outer query. You'll be referring to the same table twice in two different queries, so you'll have to use a different alias for each one.
Something like this should work:
select DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
(select count(hscore)
from amexmedscreen subq
where
hscore >= '3.5'
and subq.client_id = outerq.client_id )
from amexmedscreen outerq
group by taken_on, client_id
select DATEADD(month, DATEDIFF(month, 0, taken_on), 0),
client_id,
count(hscore),
sum(hscore),
tb1.COUNT_HSCORE
from amexmedscreen
INNER JOIN
(select client_id, count(hscore) as COUNT_HSCORE
from amexmedscreen
where hscore >= '3.5'
group by client_ID) as tb1
ON tb1.client_id = client id
group by taken_on, client_id,tb1.COUNT_HSCORE