Query for sum of all and particular rows - sql-server

How can I arrive at a query for the below scenario?
Data:
Date Product Result Total
15/01/2015 ABC Pass 5
15/01/2015 XYZ Pass 8
15/01/2015 MNO Fail 2
23/01/2015 ABC Pass 10
23/01/2015 XYZ Fail 3
I need the result in the below format:
Date Total Pass Fail
15/01/2015 15 13 2
23/01/2015 13 10 3

Use conditional Aggregate
select Date
sum(Total) Total,
SUM(case when Result ='Pass' then Total else 0 end) Pass,
SUM(case when Result ='Fail' then Total else 0 end) Fail
From yourtable
Group by Date

Try this using PIVOT . FIDDLER DEMO
SELECT Date,
sum(pass) + sum(fail) AS Total,
sum(pass) AS Pass,
sum(fail) AS Fail
FROM TableName
PIVOT (SUM(Total) FOR Result in (pass, fail)) AS P
GROUP BY Date

Related

SQL Server How do you get the sum of a column with condition that if its less than 0, add from another column else add that column?

select
sum(case when Apt.productionValue != '-1.0' then Apt.subTotal
else Apt.productionValue end) as ProductionValue,Apt.date
from Appointment Apt
group by Apt.date
order by Apt.date asc
ApppointmentID
Production Value
SubTotal
Date
1
-1
10
2021-09-02
2
10
0
2021-09-02
3
-1
20
2021-09-01
4
-1
20
2021-09-01
5
5
0
2021-09-01
I'm trying to get the sum of Production value only if it is over 0, else add subtotal instead for that row.
End goal is to still have 20 as the sum for 2021-09-02 and 45 for 2021-09-01
You were close in your attempt. This should work based on the sample data provided.
select Apt.[Date]
, sum(case when Apt.ProductionValue < 0 then Apt.SubTotal else Apt.ProductionValue end)
from Appointment Apt
group by Apt.[Date]
order by Apt.[Date]
You can select the expected column in a subquery like :
select Date, SUM(ProductionValue) as ProductionValue
from (
select
Date,
case when ProductionValue > 0
then ProductionValue
else SubTotal end
as ProductionValue
from Appointment
) as d
group by Date
order by Date

Grouping ID while counting specific attribute values

I want to count how many occurrences there is of the value 1 in the attribute months for each ID in a table.
Here is what I am working with
ID. Months
1000 1
1000 1
1000 2
1001 2
1002 3
1003 1
This is what I would like to have
ID. Count(Months=1)
1000 2
1003 1
If you want to count row for just one month, you can use WHERE clause for filtering:
select id,
count(*) as cnt
from your_table
where month = 1
group by id;
If you want to get counts for multiple months in one row (it's called pivoting), you can use conditional aggregation in most of the databases:
select id,
count(case when month = 1 then 1 end) as cnt_month_1,
count(case when month = 2 then 1 end) as cnt_month_2,
count(case when month = 3 then 1 end) as cnt_month_3,
. . .
from your_table
group by id;
Some databases offer PIVOT operator for this task. For that, you'll need to specify which database you are using.

How to query records based on row_num and one of the column value?

Rownum Status
1 2
2 1
3 3
4 2
5 3
6 1
The condition is to query records appear before the first record of status=3 which in the above scenario the expected output will be rownum = 1 and 2.
In the case if there is no status=3 then show everything.
I'm not sure from where to start hence currently no findings
If you are using SQL Server 2012+, then you can use window version of SUM with an ORDER BY clause:
SELECT Rownum, Status
FROM (
SELECT Rownum, Status,
SUM(CASE WHEN Status = 3 THEN 1 ELSE 0 END)
OVER
(ORDER BY Rownum) AS s
FROM mytable) t
WHERE t.s = 0
Calculated field s is a running total of Status = 3 occurrences. The query returns all records before the first occurrence of a 3 value.
Demo here

Select fields from differents rows

I have the following table Test
id value type
1 100 prime
1 200 13 month
2 120 prime
2 300 13 month
How can I get the following result
id valuePrime typePrime valueMonth typeMonth
1 100 prime 200 13 month
2 120 prime 300 13 month
Looking on this you could split data using type prime:
select id, value as ValPrime, 'prime' as TypePrime from tbl where type = 'prime'
then select :
select id, value as ValMonth, type as TypeMonth from tbl where type != 'prime'
and then joing them
but this is workaround, this really not good:)
Modify your schema:
id parentid value type
---------------------------
1 null 100 prime
2 1 200 13 month
3 null 120 prime
4 3 300 13 month
and query like this:
SELECT a.id, a.value AS valuePrime, a.type AS typePrime, b.value AS valueMonth, b.type AS typeMonth
FROM Test AS a
INNER JOIN Test AS b
ON a.id=b.parentid
This might work out for you although beware that this would work only in case if there are only 2 records with the same ID as you have shown above.I would still suggest a change in the schema.The following query might help you for the time being.
SELECT q1.id, q1.value AS valueprime, q1.type AS typeprime,q2.value
as valueMonth,q2.type as typeMonth
FROM Test AS q1 INNER JOIN Test AS q2 ON q1.id = q2.id AND q1.value<> q2.value

Why some dates give worse performance than other in MS SQL Server

I have a query in MS SQL Server asking for name and some date-related information, depending on two dates, a start- and an enddate.
The problem is, I´m not always getting the same performance. Whenever I request something between the dates;
2010-07-01 00:00:00.000 and
2011-07-21 23:59:59.999
the performance is excellent. I get my result within mseconds. When I request something between these dates, for example,
2011-07-01 00:00:00.000 and
2011-07-21 23:59:59.999
the performance is.. less than good, taking between 20-28 seconds for each query. Do note how the dates giving good performance is more than a year between, while the latter is 20 days.
Is there any particular reason (maybe related to how DATETIME work) for this?
EDIT: The query,
SELECT ENAME,
SUM(CASE DATE WHEN 0 THEN 1 ELSE 0 END) AS U2,
SUM(CASE DATE WHEN 1 THEN 1 ELSE 0 END) AS B_2_4,
SUM(CASE DATE WHEN 2 THEN 1 ELSE 0 END) AS B_4_8,
SUM(CASE DATE WHEN 3 THEN 1 ELSE 0 END) AS B_8_16,
SUM(CASE DATE WHEN 4 THEN 1 ELSE 0 END) AS B_16_24,
SUM(CASE DATE WHEN 5 THEN 1 ELSE 0 END) AS B_24_48,
SUM(CASE DATE WHEN 6 THEN 1 ELSE 0 END) AS O_48,
SUM(CASE DATE WHEN 7 THEN 1 ELSE 0 END) AS status,
AVG(AVG) AS AVG,
SUM(DATE) AS TOTAL
FROM
(SELECT ENAME,
(CASE
WHEN status = 'Öppet' THEN 7
WHEN DATE < 48 THEN
(CASE WHEN DATE BETWEEN 0 AND 2 THEN 0
WHEN DATE BETWEEN 2 AND 4 THEN 1
WHEN DATE BETWEEN 4 AND 8 THEN 2
WHEN DATE BETWEEN 8 AND 16 THEN 3
WHEN DATE BETWEEN 16 AND 24 THEN 4
WHEN DATE BETWEEN 24 AND 48 THEN 5
ELSE - 1 END)
ELSE 6 END) AS DATE,
DATE AS AVG
FROM
(SELECT DATEDIFF(HOUR, cases.date, status.date) AS DATE,
extern.name AS ENAME,
status.status
FROM
cases INNER JOIN
status ON cases.id = status.caseid
AND status.date =
(SELECT MAX(date) AS Expr1
FROM status AS status_1
WHERE (caseid = cases.id)
GROUP BY caseid) INNER JOIN
extern ON cases.owner = extern.id
WHERE (cases.org = 'Expert')
AND (cases.date BETWEEN '2009-01-15 09:48:25.633'
AND '2011-07-21 09:48:25.633'))
AS derivedtbl_1)
AS derivedtbl_2
GROUP BY ENAME
ORDER BY ENAME
(parts of) The tables:
Extern
-ID (->cases.owner)
-name
Cases
-Owner (->Extern.id)
-id (->status.caseid)
-date (case created at this date)
Status
-caseid (->cases.id)
-Status
-Date (can be multiple, MAX(status.date) gives us date when
status was last changed)
I would have thought a statistics issue.
When you are only selecting the most recent dates these may be unrepresented in the statistics yet as the threshold has not yet been reached that would trigger auto updating.
See this blog post for an example.

Resources