Joining two select statement in sql - sql-server

I have two select statements. 1st selectreturns data from previous year 2012, while 2nd select displays the current year. How will i join those two to get my desired output.
select a.id, b.item, a.sum(qty) as 'yr1qty', a.yr1amt from table A
left join table B on a.code = b.code
where date between '04/01/2012' and '04/07/2012'
group by a.id, b. item
select a.id, b.item, a.sum(qty) as 'yr2qty', a.yr2amt from table A
left join table B on a.code = b.code
where date between '04/01/2013' and '04/07/2013'
group by a.id, b. item
desired output:
id item yr1qty y1amt yr2qty yr2amt
01 item01 20 2000.00 5 500.00
02 item02 8 400.00
03 item03 10 1250.00
04 item04 3 60.00 2 40.00
05 item05 8 400.00

You should be able to join the two as subqueries using a full outer join
select
coalesce(a.id,b.id),
coalesce(a.item,b.item),
yr1qty,
yr1amt,
yr2qty,
yr2amt
from
(
select a.id, b.item, a.sum(qty) as 'yr1qty', a.yr1amt from table A
left join table B on a.code = b.code
where date between '04/01/2012' and '04/07/2012'
group by a.id, b. item) as a
full outer join
(
select a.id, b.item, a.sum(qty) as 'yr2qty', a.yr2amt from table A
left join table B on a.code = b.code
where date between '04/01/2013' and '04/07/2013'
group by a.id, b. item
) as b on a.id = b.id

Do you need two? Here's the result in one query ...
select a.id, b.item,
a.sum(
CASE WHEN date between '04/01/2012' and '04/07/2012'
THEN qty
ELSE 0
END) AS 'yr1qty', a.yr1amt,
a.sum(
CASE WHEN date between '04/01/2013' and '04/07/2013'
THEN qty
ELSE 0
END) AS 'yr2qty', a.yr2amt
from table A
left join table B on a.code = b.code
group by a.id, b.item

Did you need to use pivot?
select id,item, yr1qty,yr1amt, yr2qty, yr2amt from
(
select a.id, b.item, a.qty, a.amt,
case
when [date] between '2012-01-04' and '2012-07-01' then 'yr1qty'
when [date] between '2013-01-04' and '2013-07-01' then 'yr2qty'
else 'oor'
end as yrqty,
case
when [date] between '2012-01-04' and '2012-07-01' then 'yr1amt'
when [date] between '2013-01-04' and '2013-07-01' then 'yr2amt'
else 'oor'
end as yramt
from A
left join B on a.code = b.code
) x
pivot (
sum(qty) for yrqty in ([yr1qty],[yr2qty])
) qtyTotal
pivot (
sum(amt) for yramt in ([yr1amt],[yr2amt])
) amtTotal

Related

SQL Query to find deference between sum of two fields in different table

I have 3 tables as follows. I want to find balance
Table A
studentID Name
1 Bob
2 Sam
3 Sara
Table B
id studentID Credit
1 1 100
2 1 150
3 2 150
4 2 150
5 3 100
6 3 200
Table C
id studentID Amount Type
1 1 50 cash
2 1 120 card
3 2 100 cash
4 2 130 card
5 3 50 card
6 3 150 card
I want to get a result table as follows where Balance = Sum(credit) - sum(amount) where type = card.
result Table
studentID Name Credit Amount Balance
1 Bob 250 120 130
2 Sam 300 130 170
3 Sara 300 200 100
EDIT
According to his comment this is the query he has tried
select A.studentID,
A.Name,
ISNULL(SUM(B.Credit),0) as [Credit],
ISNULL(SUM(C.Amount),0) as [Amount],
ISNULL(SUM(B.Credit),0) - (select ISNULL(SUM(C.Amount),0) from C Group by C.studentID having C.Type='card' and C.studentID=A.studentID) as [balance]
from A
left outer join B on A.studentID = B.studentID
left outer join C on B.studentID = C.studentID
group by A.studentID
Handles students with no credit/amounts:
SELECT A.STUDENTID, A.[NAME]
, sum(B.CREDIT) AS [CREDIT]
, sum(C.AMOUNT) AS [AMOUNT]
, sum(B.CREDIT) - sum(C1.AMOUNT) AS [BALANCE]
FROM #TABLEA A
INNER JOIN (SELECT A.STUDENTID, isnull(SUM(B.CREDIT), 0) AS CREDIT FROM #TABLEA A LEFT JOIN #TABLEB B ON A.STUDENTID = B.STUDENTID GROUP BY A.STUDENTID) B ON A.STUDENTID = B.STUDENTID
INNER JOIN (SELECT A.STUDENTID, isnull(SUM(C.AMOUNT), 0) AS AMOUNT FROM #TABLEA A LEFT JOIN #TABLEC C ON A.STUDENTID = C.STUDENTID WHERE [TYPE] = 'CARD' GROUP BY A.STUDENTID) C ON B.STUDENTID = C.STUDENTID
INNER JOIN (SELECT A.STUDENTID, isnull(SUM(C.AMOUNT), 0) AS AMOUNT FROM #TABLEA A LEFT JOIN #TABLEC C ON A.STUDENTID = C.STUDENTID WHERE [TYPE] = 'CARD' GROUP BY A.STUDENTID) C1 ON B.STUDENTID = C1.STUDENTID
group by A.STUDENTID, A.[NAME]
This should work fine
SELECT
a.studentid,
a.Name,
sum(b.Credit) AS Credit,
ISNULL(c.Amount,0) AS Amount,
sum(b.Credit) - ISNULL(c.Amount,0) AS Balance
FROM a
INNER JOIN b ON a.studentid = b.StudentID
LEFT JOIN (select sum(amount) amount,studentid from c where type='card'
group by studentid) as c ON a.studentid = c.studentid
GROUP BY a.studentid, a.Name,c.Amount
SQL Fiddle Link
I haven't tried it. Please let me know.
SELECT A.studentID,A.Name,B.Credit,C.Amount,(Credit-Balance) as Amount from A, B, C where A.studentID=B.studentID=C.studentID AND B.id=C.id AND C.type="card";
This should work. It assumes all students in A are in B. The left join caters for the fact that not all may have a 'card' amount, and returns a 0 if they do not (otherwise a credit subtracted by a NULL will return NULL balance).
SELECT
a.StudentID,
a.Name,
sum(b.Credit) AS Credit,
ISNULL(sum(c.Amount),0) AS Amount,
sum(b.Credit) - ISNULL(sum(c.Amount),0) AS Balance
FROM tableA as a
INNER JOIN tableB as b ON a.StudentID = b.StudentID
LEFT JOIN tableC as c ON a.StudientID = c.StudentID AND c.[Type] = 'card'
GROUP BY a.StudentID, a.Name
This would be my start point. To be sure about the right calcs.
Then I'll start to refactor.
SELECT a.*,
(SELECT SUM(b.credit) FROM TableB b WHERE a.studentID = b.studentID) as Credit,
(SELECT SUM(c.amount) FROM TableC c WHERE a.studentID = c.studentID) as Amount,
((SELECT SUM(b.credit) FROM TableB b WHERE a.studentID = b.studentID)
-
(SELECT SUM(c.amount) FROM TableC c WHERE a.studentID = c.studentID)) as Balance
FROM TableA a;
I made a sqlFiddle: http://sqlfiddle.com/#!9/b86dc/7
You can try a query like below
See live demo
select A.*, credit, amount, balance= coalesce(credit,0) - coalesce(amount,0) from
[table A] A
left join
(
select
studentid,
credit= sum(credit)
from [table b] b
group by studentid
)B
on A.studentID= B.studentID
left join
(
select
studentid,
amount= sum(amount)
from [table C]
group by studentid
)C
on A.studentID=C.studentID

How to group by month of a date using a function in a select statement

I am having problems grouping by the month of a date when using a function. It was working before but the query was less complicated as I am now using a function that uses a rolling year from the current month. Here is my code.
SELECT
CASE
WHEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) < 12
THEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) + 1
ELSE 13 END AS [Expected Month],
P.probability AS [Category], COUNT(O.id) AS [Customers]
FROM opportunity_probability P
INNER JOIN opportunity_detail D ON D.probability_id = P.id
INNER JOIN opportunities O ON D.opportunity_id = O.id
INNER JOIN
(
SELECT opportunity_id
FROM opportunity_detail
GROUP BY opportunity_id
) T ON T.opportunity_id = O.customer_id
GROUP BY P.probability, MONTH(D.expected_date)
ORDER BY P.probability, MONTH(D.expected_date)
It works if I have D.expected_date in the GROUP BY but I need to group on the MONTH of this date as it does not bring through the data correctly.
You could always remove the group by, then put your entire select into another select, and than group by the outer select:
select t.A, t.B from (select A, datepart(month, b) as B) t group by t.A, t.B
This way you can address your month field as if it where a normal field.
Example is far from complete, but should get you on your way.
You can try to find month by this code:
GROUP BY P.probability, DATEPART(month, D.expected_date)
try this
SELECT
to_char(D.expected_date, 'YYYY-MM'),
CASE
WHEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) < 12
THEN DATEDIFF(mm,dbo.fn_firstofmonth(getdate()), dbo.fn_firstofmonth(D.expected_date)) + 1
ELSE 13 END AS [Expected Month],
P.probability AS [Category], COUNT(O.id) AS [Customers]
FROM opportunity_probability P
INNER JOIN opportunity_detail D ON D.probability_id = P.id
INNER JOIN opportunities O ON D.opportunity_id = O.id
INNER JOIN
(
SELECT opportunity_id
FROM opportunity_detail
GROUP BY opportunity_id
) T ON T.opportunity_id = O.customer_id
GROUP BY P.probability, to_char(D.expected_date, 'YYYY-MM')
ORDER BY P.probability, to_char(D.expected_date, 'YYYY-MM')

create sql query to fetch repeat column values within time frame

Can someone help me with this query? I want to get the result of all the customer_id which repeats more than once in 24hrs
SELECT
O.Order_No, O.Customer_ID, O.DateOrdered, O.IPAddress,
C.FirstName, C.LastName, CD.nameoncard
FROM
Order_No O
INNER JOIN
CardData CD ON O.card_id = CD.id
INNER JOIN
Customers C ON O.customer_id = C.customer_id
ORDER BY
O.order_no desc
adding more details..
so suppose order with customer id xx was placed on 04/23 2:30 pm and again 2nd order was placed with same customer Id xx on same day 04/23 5:30 pm.
i want the query to return me customer Id xx
Thanks
select Customer_ID, CAST(DateOrdered as Date) DateOrdered, count(*) QTDE
from Order_No
group by Customer_ID, CAST(DateOrdered as Date)
having count(*) > 1
To get the customers who have orders issued after the first one, then you could use the following query:
select distinct A.Customer_ID
from Order_No A
inner join (select Customer_ID, min(DateOrdered) DateOrdered from Order_No group by Customer_ID ) B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered - B.DateOrdered <= 1
and A.DateOrdered > B.DateOrdered
SQL Fiddle
To get all customers that have ANY TIME more than one order issued in period less or equal than 24h
select distinct A.Customer_ID
from Order_No A
inner join Order_No B
on A.Customer_ID = B.Customer_ID
and A.DateOrdered > B.DateOrdered
and A.DateOrdered - B.DateOrdered <= 1
SQL Fiddle
Self-join:
SELECT distinct O.Customer_ID
FROM
Order_No O
inner join Order_No o2
on o.customerID = o2.customerID
and datediff(hour, o.DateOrdered, o2.DateOrdered) between 0 and 24
and o.Order_No <> o2.Order_No
This will return all customer_IDs that have ever placed more than one order in any 24 hour period.
Edited to add the join criteria that the matching records should not be the same record. Should return customers who placed two different orders at the same time, but not customers who placed only one order.

How to get values from two tables in SQL Server?

I have 2 tables in SQL Server 2008 and I want to get the details from those 2 tables using join.
T-1 : vwHardwareConsolidate
|ID|||Qty|Type|Task_Id|
T-2 :
|MasterID|Task_Id|Act_Qty|
I want to get id, task_name, sum(qty), task_id from T1 and Masterid, Act_Qty from T2
I have tried this query
select
ID as MasterID, Task_id, Task_Name as Items,
SUM(Qty) as Req_Qty, 0 as Act_Qty
from
vwHardwareConsolidate
where
type = 'Reqrd' and ID = '21'
Group by
Task_Name,id,Task_id
union
(select
m.MasterID, m.Task_Id, vw.Task_Name as Items, 0 as Req_Qty, m.Act_Qty
from
vwHardwareConsolidate vw
Right join
(select
MasterID, m.Task_Id, 0 as Req_Qty, sum(Act_qty) as Act_Qty
from
tbl_MaterialDistribution_Detail m
where
MasterID = '21'
group by
m.Task_Id, MasterID) as m on m.Task_Id = vw.Task_id)
vwHardwareConsolidate
ID Site_name Qty Task_Name Type
1 CITY 1 A16Port_Switch Reqrd
1 CITY 1 Digital_Camera Reqrd
1 CITY 1 Electronic_Pen Reqrd
tbl_MaterialDistribution_Detail:
MasterID|TaskId|Act_qty
7 31 1
2 32 1
12 39 3
Please try this
select t1.ID, t1.Task_Name,Sum(t1.Qty) as Qty,t1.Task_Id,t2.MasterID,t2.Act_Qty
from vwHardwareConsolidate as t1
left outer join table2 as t2
on t2.Task_ID=t1.Task_ID
Group By t1.ID, t1.Site_name, t1.Task_Name,t1.Qty,t1.Type,t1.Task_Id,t2.MasterID,t2.Act_Qty
May this will help you.
SQL Fiddle Demo
You can use
SELECT T1.Id, T1.SiteName,T1.TaskName,T.Type,T2.Act_Qty,T2.MasterID,T2.Task_Id,SUM(Qty)AS
Qty FROM T1 INNER JOIN T2 ON T1.Task_Id=T2=Task_Id GROUP BY T1.Id, T1.SiteName,
T1.TaskName,T.Type,T2.Act_Qty,T2.MasterID,T2.Task_Id
something this way,
select a.id,a.Task_Name,b.qty,c.Act_Qty from vwHardwareConsolidate a inner join
tbl_MaterialDistribution_Detail c on a.id=c.task_id
inner join
(slect id,sum(qty)qty from vwHardwareConsolidate group by id)b
on a.id=b.id

T-SQL, zero sum for no match on join

I have two tables, one with all my Branches, and one with all my sales. The sales table also contains a Sales Rep ID, a Branch ID, a month and a year.
I need a query that will return the sum of a specific rep's sales for a year, grouped by branch and month, and the query must return 0 if there has been no sales in a branch for that month. I have the following, which does not return 0 if there are no sales:
SELECT
s.Month,
b.BranchName,
SUM(s.InvoiceAmount) AS 'Sales'
FROM
Branch b
INNER JOIN
Sales s ON s.BranchID = b.BranchID
WHERE
s.Year = 2008
AND
s.SalesRepID= 11
GROUP BY
s.Month,
b.BranchName
ORDER BY
s.Month,
b.BranchName
You will need to add the "missing" data to be able to join it.
SELECT
b.BranchName,
SUM(ISNULL(s.InvoiceAmount, 0)) AS 'Sales',
s.Month
FROM
Branch b
LEFT OUTER JOIN (
SELECT
b.BranchID AS BranchID
, s.SalesRepID AS SalesRepID
, Months.Month AS Month
, Years.Year AS Year
, 0 AS InvoiceAmount
FROM
Sales s
CROSS JOIN (
SELECT 1 AS Month
UNION ALL SELECT 2
UNION ALL SELECT 3
UNION ALL SELECT 4
UNION ALL SELECT 5
UNION ALL SELECT 6
UNION ALL SELECT 7
UNION ALL SELECT 8
UNION ALL SELECT 9
UNION ALL SELECT 10
UNION ALL SELECT 11
UNION ALL SELECT 12
) Months
CROSS JOIN (
SELECT 2007 AS Year
UNION ALL SELECT 2008
UNION ALL SELECT 2009
) Years
CROSS JOIN Branch b
UNION ALL SELECT
s.BranchID AS BranchID
, s.SalesRepID AS SalesRepID
, s.Month AS Month
, s.Year AS Year
, s.InvoiceAmount AS InvoiceAmount
FROM Sales s
)s ON s.BranchID = b.BranchID
WHERE
s.Year = 2008
AND s.SalesRepID= 11
GROUP BY
s.Month,
b.BranchName
ORDER BY
b.BranchName,
s.Month
You'll need to do a LEFT JOIN to Sales, so as to return even the reps that do not have any records in the Sales table.
If your query is returning NULL, you can use one of the coalescing methods: COALESCE(SUM(...), 0) will return the first non-NULL value in the list...
You need to use a left join and an isnull to get the sum right:
SELECT b.BranchName
, SUM(isnull(s.InvoiceAmount, 0)) AS 'Sales'
FROM Branch b
LEFT JOIN Sales s ON s.BranchID = b.BranchID
GROUP BY s.Month, b.BranchName
ORDER BY s.Month, b.BranchName
You still need to do some more work with it to get the months showing too if a salesman has no sales in a particular month.
I changed the join from inner to left outer and added the ISNULL function for branches with no sales.
SELECT
b.BranchName,
s.Month,
SUM(ISNULL(s.InvoiceAmount,0)) AS 'Sales'
FROM
Branch b
LEFT JOIN
Sales s ON s.BranchID = b.BranchID
WHERE
s.Year = 2008
AND
s.SalesRepID= 11
GROUP BY
s.Month,
b.BranchName
ORDER BY
s.Month,
b.BranchName

Resources