Combine two queries, which include aggregations, into a single query - sql-server

Table "tblCustomer":
Customer_id
created
field1
field2
cardno
1014
2010-05-25 12:51:59.547
Cell Phone
abc#lmn.com
1234567890
1015
2010-08-15 12:51:59.547
Email
abc#xyz.com
2345678891
Table "tbl_TransactionDishout":
Trnx_id
offerNo
TerminalID
Created
VirtualCard
1
1014
170924690436418
2010-05-25 12:51:59.547
1234567890
Expected Output:
Enrolled
Enrolled as Email
Enrolled as Text
Deals Redeemed
<First Date>
7
5
2
6
<Next Date>
9
3
6
14
I have two different queries which I need to combine into one.
First One:
SELECT CAST(FLOOR(CAST(t.created AS FLOAT )) AS Datetime) created,
COUNT(field1) Enrolled,
COUNT(CASE field1 WHEN 'E-mail' THEN 1 END) Enrolled_as_Email,
COUNT(CASE field1 WHEN 'Cell Phone' THEN 1 END) Enrolled_as_Cell
FROM tblCustomer as t
GROUP BY t.created
ORDER BY t.created DESC
Which Displays:
create
Enrolled
Enrolled_as_Email
Enrolled_as_Cell
2012-03-01 00:00:00.000
3
1
2
2012-02-29 00:00:00.000
1
0
1
Second One:
SELECT CAST(FLOOR(CAST(t.created AS FLOAT)) AS Datetime) created,
COUNT(*) [Deals_Redeemed]
FROM tbl_TransactionDishout t
LEFT JOIN tblCustomer c
ON t.VirtualCard = c.cardno
GROUP BY CAST(FLOOR(CAST(t.created AS FLOAT )) as Datetime)
ORDER BY t.created desc
Which Displays:
create
Deals_Redeemed
2012-03-02 00:00:00.000
1
2012-03-01 00:00:00.000
6
2012-02-28 00:00:00.000
1
2012-02-27 00:00:00.000
2
Now I want a record which contain date from both and should be combined into one.
But It's giving me the result of the date contained only in tblCustomer table..
How to get "Deals_redeemed"?
Note: relation between tbl_transaction and tblCustomer is having same cardno.

SELECT
CAST(t1.created AS DATE) created,
COUNT(t1.field1) Enrolled,
COUNT(CASE t1.field1 WHEN 'E-mail' THEN 1 END) Enrolled_as_Email,
COUNT(CASE t1.field1 WHEN 'Cell Phone' THEN 1 END) Enrolled_as_Cell,
COUNT(t2.created) Deals_Redeemed
FROM tblCustomer AS t1
LEFT JOIN tbl_TransactionDishout t2
ON t1.cardno = t2.VirtualCard
GROUP BY CAST(t1.created AS DATE)
ORDER BY CAST(t1.created AS DATE) DESC
Edit: Changed condition to cardno, and changed from FULL JOIN to LEFT JOIN.

You could Pivot():
select [create]
, sum([Email]+[Cell Phone]) as [Enrolled]
, max([Email]) as [Enrolled as Email]
, max([Cell Phone]) as [Enrolled as Cell Phone]
, max([Deal Redeemed]) as [Deals Redeemed]
from (
select [create]=created
, create1=created
, field1
from tblCustomer
union all
select [create]=created
, create1=created
, field1='Deal Redeemed'
from tbl_TransactionDishout
) p
pivot (
count(create1)
for field1 in ([Cell Phone],[Email],[Deal Redeemed])
) pv
group by [create]
order by [create]

Related

Date Comparison of Two Tables in SQL SERVER

I had this Data,
Table One :
EmpID Date Absent
1 01/01/2018 1
1 01/02/2018 1
1 02/05/2018 1
1 03/25/2018 1
1 04/01/2018 0
1 05/02/2018 1
1 06/03/2018 1
Table Two
ID Amount DateEffective
1 5.00 02/06/2018
2 3.00 05/02/2018
3 10.00 06/03/2018
Desired Output
EmpID Month Year Absent Penalty
1 January 2018 2 5.00
1 February 2018 1 5.00
1 March 2018 1 3.00
1 April 2018 0 3.00
1 May 2018 1 13.00
1 June 2018 1 10.00
This is my Code
SELECT { fn MONTHNAME(one.Date) } AS MonthName, YEAR(one.Date) AS Year, SUM(one.Absent) AS Absent,
(
SELECT top 1 two.DailyRate
FROM table_two as two
WHERE EmpID = '1'
AND one.Date <= two.EffectivityDate
)
FROM table_one as one
WHERE EmpID = '1'
GROUP BY { fn MONTHNAME(one.Date) }, MONTH(one.Date), YEAR(one.DTRDate)
ORDER BY Year(one.Date),month(one.Date)
and it shows an error :
Column 'one.Date' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause
please help for this issue...
Thanks
Try this :
SELECT
one.EmpID
,DATENAME(MONTH,one.Date) AS [MonthName]
,YEAR(one.Date) AS [Year]
,SUM(one.Absent) AS [Absent]
,(SELECT top 1 two.Amount
FROM table_two as two
WHERE two.ID = one.EmpID
AND YEAR(two.DateEffective) >= YEAR(one.Date)
AND MONTH(two.DateEffective) >=MONTH(one.Date)
) AS [Penalty]
FROM table_one as one
WHERE
one.EmpID = '1'
GROUP BY one.EmpID,DATENAME(MONTH,one.Date), MONTH(one.Date), YEAR(one.Date)
ORDER BY Year(one.Date),month(one.Date)
From my understanding to do this,
select e.EmpID
,datename(month,e.Date)[month]
,year(e.Date) [year]
,sum(e.Absent) as [Abscount]
,a.Amount
from
empl e left join abs a
on datename(month,e.Date)=DATENAME(month,a.DateEffective)
group by e.EmpID,DATENAME(MONTH,e.Date), MONTH(e.Date), YEAR(e.Date) , a.Amount
order by Abscount desc
Revert me if any clarifications needed...
is this helpful.?
Create Table #TabOne(EmpID int,[Date] Date,[Absent] Bit)
Create Table #TabTwo(ID int,Amount float,DateEffective Date)
Insert into #TabOne
SELECT 1,'01/01/2018',1 Union All
SELECT 1,'01/02/2018',1 Union All
SELECT 1,'02/05/2018',1 Union All
SELECT 1,'03/25/2018',1 Union All
SELECT 1,'04/01/2018',0 Union All
SELECT 1,'05/02/2018',1 Union All
SELECT 1,'06/03/2018',1
Insert into #TabTwo
Select 1,5.00 ,'02/06/2018' Union All
Select 2,3.00 ,'05/02/2018' Union All
Select 3,10.00,'06/03/2018'
;with cte1
As
(
Select One.EmpID,MONTH(one.[Date]) As [mon],YEAR(one.[Date]) As [Year],two.Amount,one.[Absent],
ROW_NUMBER() OVER(partition by One.EmpID,One.[Date] order by DATEDIFF(dd,two.DateEffective,one.[Date]) desc) as rn
from #TabOne one
LEFT JOIN #TabTwo two on one.[Date]<=two.DateEffective
)
Select EmpID,DATENAME(month, DATEADD(month, [mon]-1, CAST('2008-01-01' AS datetime))) As [Month],
[Year],SUM(CASE WHEN [Absent]=0 then 0 ELSE 1 END) As [Absent] ,MAX(Amount) As Penalty
from cte1
where rn=1
Group by EmpID,[Year],[mon]
order by EmpID,[Year],[mon]
Drop Table #TabOne
Drop Table #TabTwo

SQL Server Two Column Pivot table

I'm trying to create a PIVOT TSQL statment that totals the products by date and state/province and provides the AVG Transit Time. Here is what I have so far:
select *
from (select createdate [Date Processed],
stateprovince as [Province],
count(*) as [Total],
avg(datediff(day,createdate,t.eventdate)) as [AVG Delivery],
product
from recipient C left outer join
(select delivid, product, eventdesc, eventdate, eventcode
from deliverystatus
where delivid in (select max(deliv_id)
from deliverystatus
where eventcode = 'DELIVERED'
group by product)) as t ON c.product = t.product
where account = 3519 and consol <>'' and trknum <> '' and C.createdate between '2/4/2016' and '2/4/2016'
group by C.createdate, c.stateprovince, c.product
) as Q
pivot (
count(product)
for [Province] in (NY, IL, GA)
) as PVT
My Result is:
Date Processed Total AVG Transit NY IL GA
2016-02-04 00:00:00.000 1 8 0 0 1
2016-02-04 00:00:00.000 1 11 2 4 1
2016-02-04 00:00:00.000 1 12 0 0 0
2016-02-04 00:00:00.000 1 15 0 0 0
I need the result to be:
Date Processed Total AVG Transit NY IL GA
2016-02-04 00:00:00.000 8 11.5 2 4 2
The ultimate goal is to have the AVG Transit listed by State/Province like this:
Date Processed Total Total AVG NY AVG IL AVG GA AVG
2016-02-04 00:00:00.000 8 11.5 2 8 4 11 2 15
Thanks in advance.
You need to add a GROUP BY clause after the pivot and either take the AVG SUM or MAX value for each output column:
select [Date Processed], SUM(NY+IL+GA) AS [Total], AVG([AVG Delivery]) AS [AVG Delivery], SUM(NY) AS NY, SUM(IL) AS IL, SUM(GA) AS GA
from (select createdate [Date Processed],
stateprovince as [Province],
count(*) as [Total],
avg(datediff(day,createdate,t.eventdate)) as [AVG Delivery],
product
from recipient C left outer join
(select delivid, product, eventdesc, eventdate, eventcode
from deliverystatus
where delivid in (select max(deliv_id)
from deliverystatus
where eventcode = 'DELIVERED'
group by product)) as t ON c.product = t.product
where account = 3519 and consol <>'' and trknum <> '' and C.createdate between '2/4/2016' and '2/4/2016'
group by C.createdate, c.stateprovince, c.product
) as Q
pivot (
count(product)
for [Province] in (NY, IL, GA)
) as PVT
group by [Date Processed]

Update table with overlap date range and change status

I have a table with following column and I would like to update it as following.
The Logic is the start date take the date will be updated if overlap with following rules: take the earliest start date and enddate of the latest row with overlapping date based on member id. And the status of the remaining overlap column will be updated to 2. Hope someone could help.
ID MemberID StartDate EndDate Status
1 2 2015-01-01 2015-02-28 1
2 2 2015-02-01 2015-02-03 1
3 2 2015-02-01 2015-03-01 1
4 1 2015-02-01 2015-02-28 1
5 3 2015-02-01 2015-02-28 1
6 2 2015-05-01 2015-05-20 1
I would like to update to
ID MemberID StartDate EndDate Status
1 2 2015-01-01 2015-03-01 1
2 2 2015-01-01 2015-03-01 2
3 2 2015-01-01 2015-03-01 2
4 1 2015-02-01 2015-02-28 1
5 3 2015-02-01 2015-02-28 1
6 2 2015-05-01 2015-05-20 1
I think this should do it :
update a set
a.startdate =
(select min(startdate) from #table where memberID = a.memberID),
a.enddate =
(select max(enddate) from #table where memberID = a.memberID),
a.status =
case when a.id =
(select min(id) from #table where memberID = a.memberID)
then status else 2
end
from #table a
Try this,
---- Creating CTE for finding overlapped dates
;WITH CTE AS (
SELECT A.ID,
B.ID AS MAPPED_ID,
A.MEMBERID,
B.STARTDATE,
B.ENDDATE,
B.STATUS
FROM #YOUR_TABLE A
JOIN #YOUR_TABLE B ON B.STARTDATE <= A.ENDDATE-- Condition for finding the overlapped dates
AND B.ENDDATE >= A.STARTDATE
AND A.MEMBERID = B.MEMBERID)-- end here
UPDATE T
SET T.STARTDATE = A.STARTDATE,
T.ENDDATE = A.ENDDATE,
T.STATUS = A.STATUS
FROM #YOUR_TABLE T
JOIN (SELECT ID,
MEMBERID,
STARTDATE,
ENDDATE,
STATUS=CASE
WHEN RN > 1 THEN 2
ELSE 1
END
FROM (SELECT T.ID,
T.MEMBERID,
CS1.STARTDATE,
CS2.ENDDATE,
ROW_NUMBER() -- ROWNUMBER FOR FINDING THE STATUS
OVER(
PARTITION BY T.MEMBERID, CS1.STARTDATE, CS2.ENDDATE
ORDER BY T.ID) AS RN
FROM #YOUR_TABLE T
CROSS APPLY (SELECT CAST(MIN(STARTDATE)AS DATETIME) AS STARTDATE --- FINDING MIN(STARTDATE) FOR THE OVERLAPPED GROUP
FROM CTE A
WHERE A.ID = T.ID) CS1
CROSS APPLY (SELECT ENDDATE -- FINDING LAST ENDDATE FOR THE OVERLAPPED GROUP (IE RN=1)
FROM (SELECT ENDDATE,--- ROW_NUMBER FOR THE OVERLAPPED GROUPS
ROW_NUMBER()
OVER(
ORDER BY B.MAPPED_ID DESC) AS RN
FROM CTE B
WHERE B.ID = T.ID)A
WHERE A.RN = 1)CS2)A)A ON A.ID = T.ID
SELECT *
FROM #YOUR_TABLE

Multiple join query and sub query

Table Structures:
tblCustomer
Customer_id created field1 field2 cardno field14
------------------------------------------------------------------------------------------------
1014 2010-05-25 12:51:59.547 Cell Phone abc#lmn.com 1234567890 Test Card
1015 2010-08-15 12:51:59.547 Email abc#xyz.com 2345678891 NULL
tbl_TransactionDishout
Trnx_id offerNo TerminalID Created VirtualCard
-------------------------------------------------------------------
1 1014 170924690436418 2010-05-25 12:51:59.547 1234567890
Relation between tbl_transaction and tblCustomer is having same cardno.
Is it possible to get the result as below date-wise records:
Enrolled Enrolled as Email Enrolled as Text Deals Redeemed
<First Date> 7 5 2 6
<Next Date> 9 3 6 14
Date should be from both tables even if it has zero records..
Enrolled - Total No of records that is summation of Enrolled as Email and Enrolled as Text.
Enrolled as Email - Where field1 = 'Email' from tblCustomer table
Enrolled as Text - Where field1 = 'cell phone' from tblCustomer table
Deals Redeemed - Where field14 <> 'Test Card' from tblCustomer table and
where DishoutResponsecode = '0000' from tbl_Transaction table
My Existing Query:
SELECT
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111) created,
COUNT(CASE WHEN (t1.field1 = 'E-mail' or t1.field1 = 'Cell Phone') and (t1.field14 <> 'Test Card' or t1.field14 is null) THEN 1 END) Enrolled,
COUNT(CASE WHEN t1.field1 = 'E-mail' and (t1.field14 <> 'Test Card' and t1.field14 is null) THEN 1 END) Enrolled_as_Email,
COUNT(CASE WHEN t1.field1 = 'Cell Phone' and (t1.field14 <> 'Test Card' and t1.field14 is null) THEN 1 END) Enrolled_as_Cell,
COUNT(CASE WHEN t2.DishoutResponseCode = '0000' and (IsNull(t1.field14, '') <> 'Test Card') THEN 1 END) Deals_Redeemed
FROM tblCustomer AS t1
FULL OUTER JOIN
tbl_TransactionDishout t2
ON t1.cardno = t2.VirtualCard and t1.created = t2.created
GROUP BY
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111)
ORDER BY
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111) DESC
Last 4-5 records in tblCustomer table
created cardno field14
----------------------------------------------------------
2012-03-07 10:03:00.034 1234007600101240
2012-03-05 04:02:00.040 1234007600602122
2012-03-01 06:25:50.400 1234010400972168 Test Card
2012-03-01 30:05:30.022 555566669999 Test Card
2012-03-01 50:50:20.450 666677778888 Test Card
Last 4-5 records in tbl_TransactionDisout table
created VirtualCard DishoutResponseCode
-----------------------------------------------------------------------
2012-03-09 13:18:02.703 1234010400972168 0010
2012-03-09 13:17:35.307 1234010400972168 0002
2012-03-09 13:17:14.237 1234010400972168 0007
2012-03-09 13:16:57.650 1234010400972168 0002
2012-03-08 21:13:57.137 1234010400475686 0000
2012-03-08 16:50:38.273 1234010400972168 0002
2012-03-08 16:50:26.070 1234010400972168 0007
2012-03-08 16:49:49.793 1234010400972168 0002
So there is only one card in this with having response code '0000' and also not a 'Test Card'..But I am getting all the card with code = '0000' and also having 'Test Card' so that means field14 is not able to compare because it is from the different table and different date..
This is the result I get back with this query when I use the data that you specified in the main question:
SELECT
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111) created,
COUNT(CASE WHEN (t1.field1 = 'Email' or t1.field1 = 'Cell Phone') and (t1.field14 <> 'Test Card' or t1.field14 is null) THEN 1 END) Enrolled,
COUNT(CASE WHEN t1.field1 = 'Email' and (IsNull(t1.field14, '') <> 'Test Card') THEN 1 END) Enrolled_as_Email,
COUNT(CASE WHEN t1.field1 = 'Cell Phone' and (IsNull(t1.field14, '') <> 'Test Card') THEN 1 END) Enrolled_as_Cell,
COUNT(CASE WHEN t2.DishoutResponseCode = '0000' and (IsNull(t1.field14, '') <> 'Test Card') THEN 1 END) Deals_Redeemed
FROM
tblCustomer AS t1
FULL OUTER JOIN
tbl_TransactionDishout t2
ON t1.cardno = t2.VirtualCard
AND t1.created = t2.created
GROUP BY
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111)
ORDER BY
convert(varchar, CAST(ISNULL(t1.created,t2.created) AS DATETIME), 111) DESC
Result:
created Enrolled Enrolled_as_Email Enrolled_as_Cell Deals_Redeemed
------------------------------ ----------- ----------------- ---------------- --------------
2012/03/09 0 0 0 0
2012/03/08 0 0 0 1
2012/03/07 1 0 1 0
2012/03/05 1 0 1 0
2012/03/01 0 0 0 0

Add SubQuery in existing subquery

Table Structures:
tblCustomer
Customer_id created field1 field2 cardno
--------------------------------------------------------
1014 Test1 Cell Phone 123146 1234567890
1015 Test2 Email abc#xyz.com 2345678891
tbl_TransactionDishout
Trnx_id offerNo TerminalID Created cardno
-------------------------------------------------------------------
1 1014 170924690436418 2010-05-25 12:51:59.547 1234567890
Is it possible to get the result as below date-wise records:
Enrolled Enrolled as Email Enrolled as Text Deals Redeemed
<First Date> 7 5 2 6
<Next Date> 9 3 6 14
My current query is something like this:
select created,
count(field1) Enrolled,
count(case field1 when 'E-mail' then 1 end) Enrolled_as_Email,
count(case field1 when 'Cell Phone' then 1 end) Enrolled_as_Cell
from tblCustomer c
group by created
order by created desc
But It's giving me the result of the date contained only in tblCustomer table..
Now, How to get Deals_redeemed..?
relation between tbl_transaction and tblCustomer is having same cardno...
In my understanding table tbl_TransactionDishout is an offer, and if it is followed through a record will be inserted into tblCustomers; if not, nothing will change. So deals redeemed is count of non-existing records in tblCustomers for given cardno:
select t.created,
count(c.field1) Enrolled,
count(case c.field1 when 'E-mail' then 1 end) Enrolled_as_Email,
count(case c.field1 when 'Cell Phone' then 1 end) Enrolled_as_Cell,
count(case when c.field1 is null then 1 end) [Deals Redeemed]
from tbl_TransactionDishout t left join tblCustomer c
on t.cardno = c.cardno
group by t.created
order by t.created desc
EDIT: c.created changed to t.created

Resources