How can i compare the results of two select statements in TSQL (2014)?
my both queries:
SELECT CallDisposition, count(CallDisposition) as Count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
where (DateTime between dateadd(minute,#timespan,convert(datetime2,(GETDATE())+ #count)) AND convert(datetime2,(GETDATE())+ #count))
Group by CallDisposition
SELECT CallDisposition, count(CallDisposition) as Count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
where DateTime >= dateadd(minute,#timespan,convert(datetime2,(GETDATE())))
Group by CallDisposition
Results of Query 1:
+-----------------+-------+
| CallDisposition | Count |
+-----------------+-------+
| 2 | 2 |
| 3 | 8 |
| 4 | 8 |
| 7 | 21 |
| 10 | 16 |
| 13 | 738 |
| 14 | 45 |
| 15 | 14 |
| 19 | 8 |
| 28 | 41 |
| 29 | 12 |
| 52 | 76 |
| 55 | 1 |
+-----------------+-------+
Results of Query 2:
+-----------------+-------+
| CallDisposition | Count |
+-----------------+-------+
| 2 | 4 |
| 3 | 7 |
| 4 | 6 |
| 6 | 2 |
| 7 | 22 |
| 10 | 6 |
| 13 | 703 |
| 14 | 67 |
| 15 | 11 |
| 19 | 4 |
| 26 | 1 |
| 28 | 62 |
| 29 | 10 |
| 52 | 79 |
+-----------------+-------+
The main problem behind, the results of both queries can be different.
Based on example above: CallDisposition 6 and 26 are missing in Query 1.
CallDispoition 55 is missing in Query 2
Note: CallDispoition values 0-100 can be expected, maybe that helps?!
The expected result should look like that:
+-----------------+-------+
| CallDisposition | Count |
+-----------------+-------+
| 2 | 2 |
| 3 | 1 |
| 4 | 2 |
| 6 | 2 |
| 7 | 1 |
| 10 | 10 |
| .. | |
| .. | |
| .. | |
| 52 | 3 |
| 55 | 1 |
+-----------------+-------+
WITH S1 AS (SELECT CallDisposition, count(CallDisposition) as Count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
where (DateTime between dateadd(minute,#timespan,convert(datetime2,(GETDATE())+ #count)) AND convert(datetime2,(GETDATE())+ #count))
Group by CallDisposition
)
,S2 AS (
SELECT CallDisposition, count(CallDisposition) as Count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
where DateTime >= dateadd(minute,#timespan,convert(datetime2,(GETDATE())))
Group by CallDisposition
)
Select ISNULL(S1.CallDisposition,S2.CallDisposition) AS CallDisposition
,ABS(ISNULL(S1.COUNT,0)-ISNULL(S2.Count,0)) Count
FROM S1 FULL JOIN S2
ON S1.CallDisposition=s2.CallDisposition
Honestly I'm puzzled by your expected result and that compares the results. So my solution won't produce such a result. But maybe it helps by pointing you tte right direction.
You can to full join the results on calldisposition. That way coexisting calldisposition will be put next to each other. If for a calldisposition in one result no one exists in the other the columns of the other will be all NULL.
SELECT *
FROM (SELECT calldisposition,
count(CallDisposition) count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
WHERE (datetime BETWEEN dateadd(minute, #timespan, convert(datetime2, (getdate()) + #count))
AND convert(datetime2, (getdate()) + #count))
GROUP BY calldisposition) x
FULL JOIN (SELECT calldisposition,
count(calldisposition) count
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
WHERE datetime >= dateadd(minute, #timespan, convert(datetime2, (getdate())))
GROUP BY calldisposition) y
ON y.calldisposition = x.calldisposition;
I'd probably insert the results into a temporary table, then query that. Use a table variable:
DECLARE #Results TABLE ([Source] VARCHAR(10), CallDisposition INT, [CallCount] INT)
(Use CallCount as that's not a reserved word)
INSERT INTO #Results(CallDisposition , CallCount, [Source])
SELECT CallDisposition, count(CallDisposition) as Count, [Source] = 'Query1',
FROM [bs_Reporting].[dbo].[Termination_Call_Detail]
where (DateTime between dateadd(minute,#timespan,convert(datetime2,(GETDATE())+ #count)) AND convert(datetime2,(GETDATE())+ #count))
Group by CallDisposition
Repeat with your 2nd query, Setting Source = 'Query2' (or union with it in the above insert).
Now you can examine your #Results:
SELECT r1.* FROM #Results r1
WHERE [Source] = 'Query1'
AND NOT EXISTS (SELECT 'X' FROM #Results r2 WHERE [Source] = 'Query2' AND r2.CallDisposition = r1.CallDisposition)
(example only; possibly not the most insightful)
Please forgive any slight syntax errors; I don't have SQL Server in front of me.
Related
As I know HAVING clause is used to filter rows for each group.
I have a table that stores scores of students.
create table sc
(
`classid` int,
`studentid` int,
`score` int
);
Here is the sample data:
+---------+-----------+-------+
| classid | studentid | score |
+---------+-----------+-------+
| 1 | 1 | 50 |
| 1 | 2 | 59 |
| 1 | 3 | 80 |
| 1 | 4 | 68 |
| 1 | 5 | 70 |
| 1 | 6 | 20 |
| 1 | 7 | 90 |
| 1 | 8 | 100 |
| 1 | 9 | 25 |
| 2 | 1 | 51 |
| 2 | 2 | 59 |
| 2 | 3 | 80 |
| 2 | 4 | 68 |
| 2 | 5 | 70 |
| 2 | 6 | 30 |
| 2 | 7 | 44 |
| 2 | 8 | 80 |
| 3 | 1 | 20 |
| 1 | 11 | 30 |
| 1 | 12 | 40 |
+---------+-----------+-------+
And I want to query the max score of each class, so I wrote this SQL statement:
select *
from sc
group by classid
having score = max(score);
But the output is not what I expect. The output only prints one row.
+---------+-----------+-------+
| classid | studentid | score |
+---------+-----------+-------+
| 3 | 1 | 20 |
+---------+-----------+-------+
If you have columns in your SELECT clause that are not being aggregated by an aggregate formula like sum(), max(), avg(), etc, then those columns also need to be present in your GROUP BY. Older versions of mysql are the only RDBMS that doesn't error when you miss this step. Instead of erroring, it will just grab whichever values it wishes and give you random results every time you run.
HAVING is one of the last steps to execute in SQL (just before ORDER BY). there's some nuance there with window functions and other stuff that executes late. Because of that doing score = max(score) doesn't make much sense. Either score is aggregated at this point or it is not. You can't compare both aggregated state and non-aggregated state of that column at the same time.
Instead you want a correlated subquery:
SELECT *
FROM t1 as dt
WHERE score =
(
SELECT MAX(score)
FROM t1 as dt2
WHERE dt.classid = dt2.classid
);
Alternatively you can use window functions:
SELECT *
FROM
(
SELECT classid,
studentid,
score,
MAX(score) OVER (PARTITION BY classid) as maxclassscore
FROM t1
) dt
WHERE score = maxclassscore;
Your code is not valid, but with your actual data you get only one result as only one has 100
SELECT * FROM sc WHERE score =
(select max(score) maxscore FROM sc);
classid | studentid | score
------: | --------: | ----:
1 | 8 | 100
db<>fiddle here
So, I have to calculate total Type A where From & To in between From & To Type B based on ID.
I can't describe it in good words, so this is the example and my expected result (Column Count) :
ID | Type | From | To | Count
-------------------------------
100 | A | 10 | 14 |
100 | A | 16 | 18 |
100 | B | 12 | 14 | 1
100 | B | 11 | 13 | 1
100 | B | 17 | 18 | 1
120 | A | 5 | 10 |
120 | A | 12 | 14 |
120 | A | 18 | 20 |
120 | A | 18 | 20 |
120 | A | 22 | 24 |
120 | B | 30 | 32 | 0
120 | B | 19 | 20 | 2
120 | B | 10 | 14 | 1
Anybody can help ? I'm expecting something similar like COUNT OVER or RANK OVER without GROUP BY because the table above is not original table, its from another subquery..
Hmmmm . . . I think a correlated subquery does what you want:
select t.*,
(case when type = 'B'
then (select count(*)
from t t2
where t2.type = 'A' and
t2.from >= t.to and
t2.to <= t.from
)
end) as count
from t;
I'm not sure if the logic for between includes the endpoints. Traditionally, in SQL, it does. But if that is not your intention, then you may need < or >.
I want to convert columns to rows in SQL Server:
Id Value Jan1 Jan2
----------------------
1 2 25 35
2 5 45 45
result should be
Id Value Month 1 2
----------------------
1 2 Jan 25 35
2 5 Jan 45 45
How can I get this result? Anyone please help
What you are asking seems a little strange. If I extend your example to include columns for Feb1 and Feb2, then I see two options for transposing your columns from this:
+----+-------+------+------+------+------+
| Id | Value | Jan1 | Jan2 | Feb1 | feb2 |
+----+-------+------+------+------+------+
| 1 | 2 | 25 | 35 | 15 | 28 |
| 2 | 5 | 45 | 45 | 60 | 60 |
+----+-------+------+------+------+------+
Transpose just the month part:
select Id, Value, MonthName, MonthValue1, MonthValue2
from t
cross apply (values ('Jan',Jan1,Jan2),('Feb',Feb1,Feb2)
) v (MonthName,MonthValue1,MonthValue2)
returns:
+----+-------+-----------+-------------+-------------+
| Id | Value | MonthName | MonthValue1 | MonthValue2 |
+----+-------+-----------+-------------+-------------+
| 1 | 2 | Jan | 25 | 35 |
| 1 | 2 | Feb | 15 | 28 |
| 2 | 5 | Jan | 45 | 45 |
| 2 | 5 | Feb | 60 | 60 |
+----+-------+-----------+-------------+-------------+
Or completely transpose the month columns like so:
select Id, Value, MonthName, MonthValue
from t
cross apply (values ('Jan1',Jan1),('Jan2',Jan2),('Feb1',Feb1),('Feb2',Feb2)
) v (MonthName,MonthValue)
returns:
+----+-------+-----------+------------+
| Id | Value | MonthName | MonthValue |
+----+-------+-----------+------------+
| 1 | 2 | Jan1 | 25 |
| 1 | 2 | Jan2 | 35 |
| 1 | 2 | Feb1 | 15 |
| 1 | 2 | Feb2 | 28 |
| 2 | 5 | Jan1 | 45 |
| 2 | 5 | Jan2 | 45 |
| 2 | 5 | Feb1 | 60 |
| 2 | 5 | Feb2 | 60 |
+----+-------+-----------+------------+
rextester demo: http://rextester.com/KZV45690
This would appear to be:
select Id, Value, 'Jan' as [month], Jan1 as [1], Jan2 as [2]
from t;
You are basically just adding another column to the output.
I don't recommend using numbers as column names, nor SQL Server keywords such as month.
Here is an option that you won't have to specify up to 365 fields
Declare #YourTable table (Id int,Value int,Jan1 int,Jan2 int,Feb1 int, Feb2 int)
Insert Into #YourTable values
(1, 2, 25, 35, 100, 101),
(2, 5, 45, 45, 200, 201)
Select [Id],[Value],[Month],[1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31]
From (
Select A.Id
,A.Value
,[Month] = Left(C.Item,3)
,[Col] = substring(C.Item,4,5)
,[Measure] = C.Value
From #YourTable A
Cross Apply (Select XMLData = cast((Select A.* for XML Raw) as xml)) B
Cross Apply (
Select Item = attr.value('local-name(.)','varchar(100)')
,Value = attr.value('.','int')
From B.XMLData.nodes('/row') as A(r)
Cross Apply A.r.nodes('./#*') AS B(attr)
Where attr.value('local-name(.)','varchar(100)') not in ('ID','Value')
) C
) A
Pivot (sum(Measure) For [Col] in ([1],[2],[3],[4],[5],[6],[7],[8],[9],[10],[11],[12],[13],[14],[15],[16],[17],[18],[19],[20],[21],[22],[23],[24],[25],[26],[27],[28],[29],[30],[31]) ) p
Returns
I'm trying to calculate a month-to-date total using SQL Server 2008.
I'm trying to generate a month-to-date count at the level of activities and representatives. Here are the results I want to generate:
| REPRESENTATIVE_ID | MONTH | WEEK | TOTAL_WEEK_ACTIVITY_COUNT | MONTH_TO_DATE_ACTIVITIES_COUNT |
|-------------------|-------|------|---------------------------|--------------------------------|
| 40 | 7 | 7/08 | 1 | 1 |
| 40 | 8 | 8/09 | 1 | 1 |
| 40 | 8 | 8/10 | 1 | 2 |
| 41 | 7 | 7/08 | 2 | 2 |
| 41 | 8 | 8/08 | 4 | 4 |
| 41 | 8 | 8/09 | 3 | 7 |
| 41 | 8 | 8/10 | 1 | 8 |
From the following tables:
ACTIVITIES_FACT table
+-------------------+------+-----------+
| Representative_ID | Date | Activity |
+-------------------+------+-----------+
| 41 | 8/03 | Call |
| 41 | 8/04 | Call |
| 41 | 8/05 | Call |
+-------------------+------+-----------+
LU_TIME table
+-------+-----------------+--------+
| Month | Date | Week |
+-------+-----------------+--------+
| 8 | 8/01 | 8/08 |
| 8 | 8/02 | 8/08 |
| 8 | 8/03 | 8/08 |
| 8 | 8/04 | 8/08 |
| 8 | 8/05 | 8/08 |
+-------+-----------------+--------+
I'm not sure how to do this: I keep running into problems with multiple-counting or aggregations not being allowed in subqueries.
A running total is the summation of a sequence of numbers which is
updated each time a new number is added to the sequence, simply by
adding the value of the new number to the running total.
I THINK He wants a running total for Month by each Representative_Id, so a simple group by week isn't enough. He probably wants his Month_To_Date_Activities_Count to be updated at the end of every week.
This query gives a running total (month to end-of-week date) ordered by Representative_Id, Week
SELECT a.Representative_ID, l.month, l.Week, Count(*) AS Total_Week_Activity_Count
,(SELECT count(*)
FROM ACTIVITIES_FACT a2
INNER JOIN LU_TIME l2 ON a2.Date = l2.Date
AND a.Representative_ID = a2.Representative_ID
WHERE l2.week <= l.week
AND l2.month = l.month) Month_To_Date_Activities_Count
FROM ACTIVITIES_FACT a
INNER JOIN LU_TIME l ON a.Date = l.Date
GROUP BY a.Representative_ID, l.Week, l.month
ORDER BY a.Representative_ID, l.Week
| REPRESENTATIVE_ID | MONTH | WEEK | TOTAL_WEEK_ACTIVITY_COUNT | MONTH_TO_DATE_ACTIVITIES_COUNT |
|-------------------|-------|------|---------------------------|--------------------------------|
| 40 | 7 | 7/08 | 1 | 1 |
| 40 | 8 | 8/09 | 1 | 1 |
| 40 | 8 | 8/10 | 1 | 2 |
| 41 | 7 | 7/08 | 2 | 2 |
| 41 | 8 | 8/08 | 4 | 4 |
| 41 | 8 | 8/09 | 3 | 7 |
| 41 | 8 | 8/10 | 1 | 8 |
SQL Fiddle Sample
As I understand your question:
SELECT af.Representative_ID
, lt.Week
, COUNT(af.Activity) AS Qnt
FROM ACTIVITIES_FACT af
INNER JOIN LU_TIME lt ON lt.Date = af.date
GROUP BY af.Representative_ID, lt.Week
SqlFiddle
Representative_ID Week Month_To_Date_Activities_Count
41 2013-08-01 00:00:00.000 1
41 2013-08-08 00:00:00.000 3
USE tempdb;
GO
IF OBJECT_ID('#ACTIVITIES_FACT','U') IS NOT NULL DROP TABLE #ACTIVITIES_FACT;
CREATE TABLE #ACTIVITIES_FACT
(
Representative_ID INT NOT NULL
,Date DATETIME NULL
, Activity VARCHAR(500) NULL
)
IF OBJECT_ID('#LU_TIME','U') IS NOT NULL DROP TABLE #LU_TIME;
CREATE TABLE #LU_TIME
(
Month INT
,Date DATETIME
,Week DATETIME
)
INSERT INTO #ACTIVITIES_FACT(Representative_ID,Date,Activity)
VALUES
(41,'7/31/2013','Chat')
,(41,'8/03/2013','Call')
,(41,'8/04/2013','Call')
,(41,'8/05/2013','Call')
INSERT INTO #LU_TIME(Month,Date,Week)
VALUES
(8,'7/31/2013','8/01/2013')
,(8,'8/01/2013','8/08/2013')
,(8,'8/02/2013','8/08/2013')
,(8,'8/03/2013','8/08/2013')
,(8,'8/04/2013','8/08/2013')
,(8,'8/05/2013','8/08/2013')
--Begin Query
SELECT AF.Representative_ID
,LU.Week
,COUNT(*) AS Month_To_Date_Activities_Count
FROM #ACTIVITIES_FACT AS AF
INNER JOIN #LU_TIME AS LU
ON AF.Date = LU.Date
Group By AF.Representative_ID
,LU.Week
I have a table comparisons. If I run
SELECT comparisonID,stu1Vers,stu2Vers,stu1,stu2
from comparisons
WHERE stu1!=stu2 and assignmentid=9;
I get something like:
+--------------+----------+----------+------+------+
| comparisonID | stu1Vers | stu2Vers | stu1 | stu2 |
+--------------+----------+----------+------+------+
| 287 | 12 | 2 | 1 | 6 |
| 286 | 12 | 1 | 1 | 6 |
| 276 | 11 | 2 | 1 | 6 |
| 275 | 11 | 1 | 1 | 6 |
| 266 | 10 | 2 | 1 | 6 |
| 265 | 10 | 1 | 1 | 6 |
| 257 | 9 | 2 | 1 | 6 |
| 256 | 9 | 1 | 1 | 6 |
...
| 391 | 19 | 1 | 1 | 6 |
| 392 | 19 | 2 | 1 | 6 |
+--------------+----------+----------+------+------+
I'd like to select the entire row where stu1Vers+stu2Vers is the maximum. I keep trying something along the lines of
select c.comparisonid,c.stu1vers,c.stu2vers,max(totvers)
from comparisons as c join
(select comparisonid, stu1vers+stu2vers as totvers
from comparisons where stu1!=stu2 group by comparisonid) as cm
on c.comparisonid = cm.comparisonid and c.stu1vers+c.stu2vers = cm.totvers;
but that returns a rather random assortment of things:
+--------------+----------+----------+--------------+
| comparisonid | stu1vers | stu2vers | max(totvers) |
+--------------+----------+----------+--------------+
| 220 | 1 | 1 | 21 |
+--------------+----------+----------+--------------+
I'm trying to get row 392 in the first table.
If you want all the rows when there are multiple rows with the same maximum value, then you can use this query:
SELECT * FROM Table1
WHERE stu1Vers + stu2Vers = (SELECT MAX(stu1Vers + stu2Vers) FROM Table1)
Including your condition:
SELECT * FROM Table1
WHERE stu1Vers + stu2Vers = (
SELECT MAX(stu1Vers + stu2Vers)
FROM Table1
WHERE stu1!=stu2 and assignmentid=9
) AND stu1!=stu2 and assignmentid=9
Result:
392, 19, 2, 1, 6
Regarding your update to the question, I'm not sure what you mean to return all the rows grouped by stu1 and stu2. Perhaps you mean ordered by these columns? If so, add ORDER BY stu1, stu2 to the query.
How about something like:
SELECT TOP 1 comparisonid, stu1vers, stu2vers, stu1Vers + stu2Vers AS MaxValue
FROM comparisons
ORDER BY MaxValue DESC
Have you tried something like this?
SELECT comparisonID,stu1Vers,stu2Vers,stu1,stu2, max(stu1Vers + stu2Vers) as maximum
from comparisons
WHERE stu1!=stu2 and assignmentid=9 order by maximum desc limit 1;