I struggle with the last part below, the "with recursive". Of course I could loop over TimestampOrigin using C#, for every day in the database. Which would mean hundreds of times the same query. But it may be possible with one query using "with recursive".
Test data:
CREATE TABLE tblData(
Id INT, ComputerName TEXT, TimestampOrigin TEXT, Timestamp TEXT, Number INT
);
DELETE FROM tblData;
INSERT INTO tblData VALUES (1, "Computer1", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 35);
INSERT INTO tblData VALUES (2, "Computer2", '2021-02-10 12:00:00', '2021-02-27 12:00:00', 24);
INSERT INTO tblData VALUES (3, "Computer3", '2021-02-09 12:00:00', '2021-02-26 12:00:00', 23);
INSERT INTO tblData VALUES (3, "Computer4", '2021-02-09 12:00:00', '2021-02-26 12:00:00', null);
INSERT INTO tblData VALUES (4, "Computer5", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 7);
INSERT INTO tblData VALUES (5, "Computer6", '2021-02-08 12:00:00', '2021-02-25 12:00:00', 0);
INSERT INTO tblData VALUES (7, "Computer7", '2021-02-07 12:00:00', '2021-02-24 12:00:00', 9);
Query grouped by TimestampOrigin:
SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL GROUP BY DATE(TimestampOrigin) ORDER BY TimestampOrigin DESC
What I need is for every day the sum for the current up to Timestamp which is current day +17 days. Example for day 2021-02-08, sum of all rows with TimestampOrigin 2021-02-08 up to 2021-02-08 +17 days (column Timestamp).
Don't know if the extra column Timestamp which is noon time of TimestampOrigin +17 days is really required. But the over time query was the reason why I created it at the very beginning of the project.
SELECT DATE(TimestampOrigin) AS TimestampOrigin,
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM tblData WHERE Number NOT NULL AND DATE(TimestampOrigin) >= DATE('2021-02-08') AND DATE(TimestampOrigin) <= DATE('2021-02-08', '+17 day')
Instead of executing the above query hundreds of times for each day and sum, I thought "with recursive" is the right approach". But was not able so far to make it work. Where to add the 17 days?
WITH RECURSIVE cte AS (
SELECT Id, ComputerName, Timestamp, DATE(Timestamp,'+1 day') totime, Number, TimestampOrigin
FROM tblData
UNION ALL
SELECT Id, ComputerName, DATE(Timestamp,'+1 day'), DATE(totime,'+1 day'), Number, TimestampOrigin
FROM cte
WHERE Number NOT NULL AND DATE(Timestamp,'+1 day') < DATE('2021-02-11')
)
SELECT DATE(TimestampOrigin),
SUM(CASE WHEN Number < 1 THEN 1 ELSE 0 END) AS Less1,
SUM(CASE WHEN Number >= 0 AND Number < 10 THEN 1 ELSE 0 END) AS Less10,
SUM(CASE WHEN Number >= 10 AND Number < 25 THEN 1 ELSE 0 END) AS Less25
FROM cte GROUP BY DATE(TimestampOrigin) ORDER BY DATE(TimestampOrigin) DESC
Expected result would be (Like when I would run the above query for each of the 4 days in the test data):
There is no need for a recursive CTE.
Join the distinct TimestampOrigins to the table under your condition and aggregate:
SELECT t1.TimestampOrigin,
SUM(t2.Number < 1) AS Less1,
SUM(t2.Number >= 0 AND t2.Number < 10) AS Less10,
SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblData) t1
INNER JOIN tblData t2
ON DATE(t2.TimestampOrigin) BETWEEN t1.TimestampOrigin AND DATE(t1.TimestampOrigin, '+17 days')
GROUP BY t1.TimestampOrigin
ORDER BY t1.TimestampOrigin DESC
See the demo.
Results:
TimestampOrigin
Less1
Less10
Less25
2021-02-10
0
0
1
2021-02-09
0
0
2
2021-02-08
1
2
2
2021-02-07
1
3
2
The result was wrong. I've found that my initial query was wrong. But with the solution from #forpas it worked at the end.
Initial single query
SELECT
SUM(Number < 1) AS Less1,
SUM(Number >= 1 AND Number < 10) AS Less10,
SUM(Number >= 10 AND Number < 25) AS Less25
FROM tblPCHardwareInformation WHERE UniqueInventoryKey IN
(
SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE('2020-10-09') AND DATE('2020-10-09', '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
)
Result:
SELECT t1.TimestampOrigin,
SUM(t2.Number < 1) AS Less1,
SUM(t2.Number >= 1 AND t2.Number < 10) AS Less10,
SUM(t2.Number >= 10 AND t2.Number < 25) AS Less25
FROM (SELECT DISTINCT DATE(TimestampOrigin) TimestampOrigin FROM tblPCHardwareInformation) t1
INNER JOIN tblPCHardwareInformation t2
ON UniqueInventoryKey IN
(
SELECT UniqueInventoryKey FROM tblPCHardwareInformation WHERE Number NOT NULL AND DATE(Timestamp) BETWEEN DATE(t1.TimestampOrigin) AND DATE(t1.TimestampOrigin, '+17 day') GROUP BY ComputerName ORDER BY Timestamp DESC
)
GROUP BY t1.TimestampOrigin
ORDER BY t1.TimestampOrigin DESC
is't possible to set 2 counts in the same row.
my result from query is like this:
enter image description here
and i will that the end result seem like this :
enter image description here
and at the end build the precent count1 to count2
my attempt trough case was not successful : SELECT Date,Shift , CASE description WHEN 'Defects' THEN count ELSE 0 END AS Defect_Count , CASE description WHEN 'Total' THEN count ELSE 0 END AS Total_Count FROM ("Queries union)
Here you go. Hope this helps. Thanks.
MYSQL:
select
t.dates, t.shift,
sum(case when t.description = 'Defects' then t.counts else 0 end) as `Defects`,
sum(case when t.description = 'Total' then t.counts else 0 end) as `Total`
from (
select *
from tbl ) t
group by t.dates, t.shift
order by t.dates, t.shift
ORACLE:
SELECT dates, shift, defects , total
FROM
(
SELECT *
FROM tbl
)
PIVOT
(
sum(counts)
FOR description IN ('Defects' as defects, 'Total' as total)
)
ORDER BY dates
Result:
dates shift Defects Total
2018-01-20 AM 21 56
2018-01-20 PM 19 54
2018-01-23 AM 16 58
2018-01-23 PM 20 45
many Thanks is working for the first Step (counts in the same Row).
i will try now to build the percent (Defects to Total).
Thanks.
to build the percent (defects to Total):
select dates,shift,defects,total,round((100*defects/total),2) Percent2Total from(select t.dates, t.shift,
sum(case when t.description = 'Defects' then t.counts else 0 end) as 'Defects',
sum(case when t.description = 'total' then t.counts else 0 end) as 'Total'
from (
select *
from tbl ) t
group by t.dates, t.shift
)q order by dates,Shift.
may be it's possible to build that only with Pivot or?
Assume I have a table like
how can I create a table like
where the groups are created of timeintervals with the length of 1 second.
Thank you in advance!
Here is an idea, but you need a table of numbers
select (m.startts + n.n - 1) as starttime,
(m.startts + n.n) as enddtime,
sum(case when vehicle_type = 'bus' then 1 else 0 end) as bus,
sum(case when vehicle_type = 'car' then 1 else 0 end) as car
from (select min(Timestamp) as startts from table t) m cross join
(select 1 as n union all select 2 union all select 3) n left join
table t
on t.timestamp >= m.startts + n.n - 1 and
t.timestamp < m.startts + n.n
group by m.startts + n.n;
This is a little dangerous because of the floating point arithmetic, but it will probably work for your purposes.
I'm trying to figure out how to count the number of occurrences based on a case statement:
select
case
when name.ssn > 0
then 'YES'
when name.taxid > 0
then 'NO'
else 'OTHER' end "Category",
name.created
from
name
where
name.id = 11111
I now want to return the count of YESs, OTHERs, and NOs in one column but can't seem to figure out how to do that.
You just need to count the result over group by statement
select count(col),col from(
select
case
when name.ssn > 0
then 'YES'
when name.taxid > 0
then 'NO'
else 'OTHER' end as col,
name.created
from
name
where
name.id = 11111
) group by col;
I am building a query within SQL Server that is calculating scores we receive for our surveys. We have a column called overall_score, where the user inputs a number from 1-5 as a rating. I am trying to create a stored procedure that will calculate ratings based off the scores.
Score rating = (Total count of scores 4 and 5)/(Total number of responses) * 100
I have three separate select statements that create results I need, but when I go to combine them together my output is 0.
Can someone please guide me on what I am doing wrong here?
Separate SQL Statements:
SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 4;
SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 5;
SELECT count(overall_score) FROM Layer1_DataMerge;
Combined together:
SELECT distinct
(
(
(SELECT count(overall_score) FROM Layer1_DataMerge WHERE Overall_Score = 4) +
(SELECT count(overall_score) FROM Layer1_DataMerge WHERE overall_score = 5)
) / (SELECT count(overall_score) FROM Layer1_DataMerge)
) AS CSAT
FROM Layer1_DataMerge;
Well the reason you're getting zero is because you're doing integer division. With integer division 1/3 = 0. You need to convert to floating-point arithmetic, plus you can do it all in one query:
SELECT 100.0 *
(SUM(CASE WHEN overall_score = 4 THEN 1 ELSE 0 END) +
SUM(CASE WHEN overall_score = 5 THEN 1 ELSE 0 END)) /
COUNT(overall_score)
or
SELECT 100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
To only show 2 decimals you can either cast to a numeric type with 2 decimals:
SELECT CAST(
100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
AS NUMERIC(5,2))
Or use STR to convert to a string:
SELECT STR(
100.0 *
SUM(CASE WHEN overall_score IN (4,5) THEN 1 ELSE 0 END) /
COUNT(overall_score)
,5,2)