Join Group By Columns Vertically - sql

I have multiple group by queries that I need to be join horizontally. Here is what I have.
Here is what I need. Is this doable?
select
Group,
Count([Total # Records]
from table
select
Group,
Count([Total # Records]
from table
where
[Date] < DATEADD(DAY, -60, getdate())

Use conditional aggregation:
select Group, Count([Total # Records]),
sum(case when [Date] < DATEADD(DAY, -60, getdate() then 1 else 0 end)
from table
group by group;

You can use the conditional aggregation using COUNT aggregate function as follows:
select group,
count([Total # Records]),
count(case when [Date] < DATEADD(DAY, -60, getdate()) then 1 end)
from table
group by group;
COUNT will ignore the null values produced by the conditions so it will give count of the records which fulfills the condition.

Below is script of the solution I ultimately used. A full working copy and sample databae can be found at Fiddle
;with table1CTE
as
(
select
[Groups],
sum([total # records]) as [total # records]
from
tbl1
where
[Groups]
in
(
select
[groups]
from
(
select
[groups],
[total # records]
from
tbl1
) as sourceTbl1
pivot
(sum ([total # records])
for [groups]
in
([Central Business],
[Venture Capital])
) as pvt
)
group by [groups]
),--table1CTE
table2CTE as
(
select
[Groups],
sum([No Action Over 60 Days]) as [No Action Over 60 Days]
from
tbl2
where
[Groups]
in
(
select
[groups]
from
(
select
[groups],
[No Action Over 60 Days]
from
tbl1
) as sourceTbl1
pivot
(sum ([No Action Over 60 Days])
for [groups]
in
([Central Business],
[Venture Capital])
) as pvt
)
group by [groups]
)--table2CTE
select
table1CTE.groups,
table1CTE.[total # records],
table2CTE.[No Action Over 60 Days]
from table1CTE left join table2CTE on table1CTE.[Groups] = table2CTE.[Groups]

Related

SQL Rollup to Sum Totals of a Grouped Table

I have a table that is grouped by 'Group Type'. What I need is for the last row to display the sum of the values in the above rows in the Total row.
Below is the code currently but I am not sure how to sum multiple fields at once.
Actual
Expected Result
Do I need to add another CASE statement to
select
CASE when GROUP_TYPE is null then 'Total' ELSE GROUP_TYPE END as 'Group Type',
Sum_Amount, TotalER, [Discount Report]
from
(select GROUP_TYPE, sum(cast(AMOUNT as float)) as Sum_Amount FROM [dbo].[a]
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
group by GROUP_TYPE with rollup) a
left join
(select [Charge Group] , sum(cast([Earned Revenue] as float)) as
TotalER, sum(cast(Discount as float)) as 'Discount Report'
from [dbo].[er] group by [Charge Group]) er
on
a.GROUP_TYPE = er.[Charge Group]
select sum(cast([er] as float)) from [dbo].[er]
I would do a union all before the aggregation. This makes it easier to specify the multiple aggregation sets:
select coalesce(group_type, 'Total') as group_type, -- the easy way
sum(amount) as sum_amount, sum(er) as totaler, sum(discount) as discount
from ((select group_type, cast(amount as float) as Amount, 0 as ER, 0 as discount
from [dbo].a
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
) union all
(select [Charge Group], 0, cast([Earned Revenue] as float) as er, cast(Discount as float)
from [dbo].er
where cast(ACTIVITY_DATE as date) between #startdate and #enddate
)
) aer
group by grouping sets ( (group_type), () );

SQL find duplicate records from past 7 days

Hi I am trying to find duplicate webvisits within the past 7 days, I have built a query but it is taking too long to run. Any help in optimizing this query would be much appreciated. I am finding duplicates using the visitorguid.
WITH TooClose
AS
(
SELECT
a.visitid AS BeforeID,
b.visitID AS AfterID,
a.omniturecid as [Before om id],
b.omniturecid as [after om id],
a.pubid as [Before pub id],
b.pubid as [after pub id],
a.VisitorGuid as [Before guid],
b.VisitorGuid as [after guid],
a.date as [Before date],
b.date as [after date]
FROM
webvisits a
INNER JOIN WebVisits b ON a.VisitorGuid = b.VisitorGuid
AND a.date < b.Date
AND DATEDIFF(DAY, a.date, b.date) < 7
Where a.Date >= '7/1/2015')
SELECT
*
FROM
TooClose
WHERE
BeforeID NOT IN (SELECT AfterID FROM TooClose)
If I understand your question correctly, you are trying to find all duplicate webvisits within the past 7 days. Not sure what qualifies as a duplicate webvisit, but here is my attempt to what might work for you:
;WITH q1
AS (
SELECT a.VisitorGuid
,a.date
FROM webvisits a
WHERE a.DATE >= DATEADD(DAY, -7, cast(getdate() as date))
)
,q2 AS
(SELECT q1.VisitorGuid
,count(*) as rcount
FROM q1
GROUP BY q1.VisitorGuid
)
SELECT q2.VisitorGuid
FROM q2
WHERE q2.rcount > 1
SQL Fiddle Demo
UPDATED
;WITH q1
AS (
SELECT a.VisitorGuid
,a.date
,a.omniturecid
FROM webvisits a
WHERE a.DATE >= DATEADD(DAY, -7, cast(getdate() as date))
)
,q2 AS
(SELECT q1.VisitorGuid
,count(*) as rcount
FROM q1
GROUP BY q1.VisitorGuid
HAVING Count(*)> 1
)
SELECT q1.VisitorGuid,
q1.omniturecid,
q1.date
FROM q1
INNER JOIN q2 on q1.VisitorGuid = q2.VisitorGuid
SQL Fiddle Demo2
As others have pointed out, it is a good idea to provide sample data. Preferable as an sqlfiddle or as create and insert statements. Here's one approach, I'm to lazy to invent the structure and fill it with data to test with, so it might contain some errors:
SELECT ... FROM (
SELECT VisitorGuid
, date
, lead(date) over (partition by visitorguid
order by date) as next_date
, omniturecid
, lead(omniturecid) over (partition by visitorguid
order by date) as next_omniturecid
, ...
, lead(...) ...
FROM webvisits a
) as x
WHERE DATEDIFF(DAY, date, next_date) < 7

Adding total column and row to sql server pivot

I have a pivot table that I believe to be working. I want to add a total column and a total row to this pivot. Here is the code for the pivot table...
SELECT Month,
[N] AS Expected,
[R] AS Requested,
[T] AS Tires,
[U] AS Unexpected,
[D] AS Damage
FROM (
SELECT CustomerNo,
DATEPART(mm,InvoiceDate) AS Month,
[Type],
SUM(Total) AS Cost
FROM tbl_PM_History
WHERE (InvoiceDate >= #Start)
AND (InvoiceDate <= #End)
AND (CustomerNo = #Cust)
GROUP BY CustomerNo,
DATEPART(mm,InvoiceDate),
TYPE
) p
PIVOT (SUM(Cost) FOR [Type] IN ([N],[R],[T],[U],[D]))AS pvt
ORDER BY Month
Here's a fairly quick way (in programming time) to achieve what you want:
;
WITH details -- Wrap your original query in a CTE so as to encapsulate all your calculations
AS (
SELECT Month,
[N] AS Expected,
[R] AS Requested,
[T] AS Tires,
[U] AS Unexpected,
[D] AS Damage,
ISNULL([N],0) + ISNULL([R],0) + ISNULL([T],0) + ISNULL([U],0) + ISNULL([D], 0) as Total
FROM (
SELECT CustomerNo,
DATEPART(mm,InvoiceDate) AS Month,
[Type],
SUM(Total) AS Cost
FROM tbl_PM_History
WHERE (InvoiceDate >= #Start)
AND (InvoiceDate <= #End)
AND (CustomerNo = #Cust)
GROUP BY CustomerNo,
DATEPART(mm,InvoiceDate),
TYPE
) p
PIVOT (SUM(Cost) FOR [Type] IN ([N],[R],[T],[U],[D])) AS pvt
)
, summary // Use another CTE to add a total line, using UNION ALL
AS (
SELECT Month
, Expected,
, Requested
, Tires
, Unexpected
, Damage
, Total
, 0 as RecordCode
FROM details
UNION ALL
SELECT Null
, SUM(Expected)
, SUM(Requested)
, SUM(Tires)
, SUM(Unexpected)
, SUM(Damage)
, SUM(Total)
, 1
FROM details
)
SELECT Month -- Do your actual sorting.
, Expected,
, Requested
, Tires
, Unexpected
, Damage
, Total
FROM summary
ORDER by RecordCode, Month

Group a query by every month

I have the following query :
select
(select Sum(Stores) from XYZ where Year = '2013' and Month = '8' )
-
(select Sum(SalesStores) from ABC where Year = '2013' and Month = '8') as difference
Here in the above query Year and Month are also columns of a table.
I would like to know if there is a way to run the same query so that , it is run against every month of the year ?
If there are months without data/rows within XYZ or ABC tables then I would use FULL OUTER JOIN:
SELECT ISNULL(x.[Month], y.[Month]) AS [Month],
ISNULL(x.Sum_Stores, 0) - ISNULL(y.Sum_SalesStores, 0) AS Difference
FROM
(
SELECT [Month], Sum(Stores) AS Sum_Stores
FROM XYZ
WHERE [Year] = '2013'
GROUP BY [Month]
) AS x
FULL OUTER JOIN
(
SELECT [Month], Sum(SalesStores) AS Sum_SalesStores
FROM ABC
WHERE [Year] = '2013'
GROUP BY [Month]
) AS y ON x.[Month] = y.[Month]
;WITH Months(Month) AS
(
SELECT 1
UNION ALL
SELECT Month + 1
FROM Months
where Month < 12
)
SELECT '2013' [Year], m.Month, COALESCE(SUM(Stores), 0) - COALESCE(SUM(SalesStores), 0) [Difference]
FROM months m
LEFT JOIN XYZ x ON m.Month = x.Month
LEFT JOIN ABC a ON a.Month = m.Month
GROUP BY m.Month
You could use GROUP BY in your inner trades, and then run a join, like this:
SELECT left.Month, (left.sum - COALESCE(right.sum, 0)) as difference
FROM (
SELECT Month, SUM(Stores) as sum
FROM XYZ WHERE Year = '2013'
GROUP BY Month
) left
LEFT OUTER JOIN (
SELECT Month, SUM(Stores) as sum
FROM ABC WHERE Year = '2013'
GROUP BY Month
) right ON left.Month = right.Months
Note the use of COALESCE. It lets you preserve the value of the first SUM in case when there are no records for the month in the ABC table.
In the following example uses the UNION ALL operator with CTE
;WITH cte AS
(SELECT SUM(Stores) AS Stores, [Month]
FROM dbo.XYZ
WHERE [Year] = '2013'
GROUP BY [Month]
UNION ALL
SELECT -1.00 * SUM(SalesStores), [Month]
FROM dbo.ABC
WHERE [Year] = '2013'
GROUP BY [Month]
)
SELECT [Month], SUM(Stores) AS Difference
FROM cte
GROUP BY [Month]
Demo on SQLFiddle
;WITH Months(Month) AS
(
SELECT 1
UNION ALL
SELECT Month + 1
FROM Months
where Month < 12
)
SELECT Months. Month ,
(select isnull(Sum(Stores),0) from XYZ where Year = '2013' and Month = Months.Month) - (select isnull(Sum(SalesStores),0) from ABC where Year = '2013' and Month =Months.Month) as difference
FROM Months

How to do join for my sitaution

i have two select statement from two different table and the common join field a datefield
one date field name is JobFinishedDate and it is from MyJobs table and another date field name is createddate and it is from DailyFinishJobsHistory table
here is my two independent sql
sql 1
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours]
from DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112)>='20131015' AND CONVERT(varchar,createddate,112)<='20131021'
group by createddate
sql 2
Select
convert(varchar,JobFinishedDate,112) as JobFinishedDate
, Count(*) [Number of techs]
From
(
select
convert(varchar,JobFinishedDate,112) JobFinishedDate,Specialist
from MyJobs
where convert(varchar,JobFinishedDate,112)>='20131015'
and convert(varchar,JobFinishedDate,112) <='20131021'
and JobState='FINISHED'
group by convert(varchar,JobFinishedDate,112) , Specialist
) t1
Group By
JobFinishedDate
now i have to join. i tried like this way but right syntax is not coming to my mind to join this way.
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours],
(
Select
convert(varchar,JobFinishedDate,112) as JobFinishedDate
, Count(*) [Number of techs]
From
(
select
convert(varchar,JobFinishedDate,112) JobFinishedDate,Specialist
from bbajobs
where convert(varchar,JobFinishedDate,112)>='20131015'
and convert(varchar,JobFinishedDate,112) <='20131021'
and JobState='FINISHED'
group by convert(varchar,JobFinishedDate,112) , Specialist
) t1
Group By
JobFinishedDate
) a
from DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112)>='20131015' AND CONVERT(varchar,createddate,112)<='20131021'
group by createddate
so please help me bit to build the join. thanks
EDIT
i tried this script also but [Number of techs] is getting NULL
SELECT CONVERT(varchar,createddate,101) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours],
(
SELECT
--CONVERT(varchar,JobFinishedDate,112) as JobFinishedDate,
COUNT(*) [Number of techs]
From
(
SELECT CONVERT(varchar,JobFinishedDate,112) JobFinishedDate,
Specialist
FROM bbajobs
WHERE d.createddate=JobFinishedDate AND
JobState = 'FINISHED'
GROUP BY CONVERT(varchar,JobFinishedDate,112), Specialist
) t1
GROUP BY JobFinishedDate
) [Number of techs]
FROM DailyFinishJobsHistory d
WHERE CONVERT(varchar,createddate,112) >= '20131015' AND CONVERT(varchar,createddate,112) <= '20131021'
GROUP BY createddate
Something like this should do the trick:
SELECT *
FROM
(
SELECT CONVERT(varchar,createddate,112) as [Date],
SUM([No of Jobs]) as [No of Jobs],
SUM([Turnaround Time]) as [Turnaround Time],
SUM([One Day Per]) as [One Day Per],
ROUND((SUM([No of Jobs]) * SUM([Turnaround Time])),2) as [TOTAL hours]
FROM DailyFinishJobsHistory
WHERE CONVERT(varchar,createddate,112) >= '20131015'
AND CONVERT(varchar,createddate,112) <= '20131021'
GROUP BY createddate
) A
JOIN
(
SELECT
JobFinishedDate,
COUNT(*) [Number of techs]
From
(
SELECT CONVERT(varchar,JobFinishedDate,112) JobFinishedDate
FROM MyJobs
WHERE CONVERT(varchar,JobFinishedDate,112) >= '20131015'
AND CONVERT(varchar,JobFinishedDate,112) <='20131021'
AND JobState = 'FINISHED'
) t1
GROUP BY JobFinishedDate
) B
ON B.JobFinishedDate = A.[Date]
See joining two select statements for a simpler example.