The question is as follows:
How high was the average purchase amount in the morning (05-11) compared to (17-23) in the evening?
I don't know how to compare them.
I tried this but I only get one big amount.
select avg(purchase_amount)
from case_data_order
where cast (create_timestamp as time ) between '05:00:00' and '11:00:00'
or cast(create_timestamp as time) between '17:00:00' and '23:00:00';
I use Postgres 9.6
try going with FILTER predicate, like this:
SELECT
count(*) AS unfiltered,
count(*) FILTER (WHERE i < 5) AS filtered
FROM generate_series(1,10) AS s(i);
unfiltered | filtered
------------+----------
10 | 4
(1 row)
so in your case it would be something like
select
avg(purchase_amount) FILTER (where cast (create_timestamp as time ) between '05:00:00' and '11:00:00') as morning
, avg(purchase_amount) FILTER (where cast (create_timestamp as time ) between '17:00:00' and '23:00:00') as evening
from case_data_order
How to get the averages:
select d,
avg(case when t between '05:00:00' and '11:00:00' then purchase_amount end) as am,
avg(case when t between '17:00:00' and '23:00:00' then purchase_amount end) as pm
from
(
select purchase_amount,
cast(create_timestamp as time) as t,
cast(create_timestamp as date) as d
from case_data_order
) dt
group by d
smth like could help:
SELECT
AVG(purchase_amount),
CASE
WHEN CAST(create_timestamp AS TIME) BETWEEN '05:00:00' AND '11:00:00'
THEN 'day'
WHEN CAST(create_timestamp AS TIME) BETWEEN '17:00:00' AND '23:00:00'
THEN 'night'
END gr
FROM case_data_order
WHERE CAST(create_timestamp AS TIME) BETWEEN '05:00:00' AND '11:00:00'
OR CAST(create_timestamp AS TIME) BETWEEN '17:00:00' AND '23:00:00'
GROUP BY
CASE
WHEN CAST(create_timestamp AS TIME) BETWEEN '05:00:00' AND '11:00:00'
THEN 'day'
WHEN CAST(create_timestamp AS TIME) BETWEEN '17:00:00' AND '23:00:00'
THEN 'night'
END gr;
Related
I'm attempting to count number of ids active during a given hourly window and day. I have three columns: start_time, end_time, and id.
Most of the groups are standard same-day groupings, i.e., 9am-11am, 11am-1pm, etc.
One of the groupings overlaps two days (11pm-1am). That is, May 16 11:01 PM and May 17 12:01 AM should be in the same group. But when composing a simple query, you'd end up grouping May 17 12:01 AM within the May 17 11:00pm.
I've tried several queries with several variations of case statements and subqueries, but can't get the gist.
This below query attempt gives me 0 for 11pm_1am column. I figured I could just move a 12:30 AM time into the previous date and count it there, but no luck.
select date_trunc('day', start_time_1) as date_active
, count(distinct(case when CAST(start_time_1 AS TIME) <= '06:00:00' and CAST(end_time_1 AS TIME) >= '01:00:00' then id end)) as early_morning
, count(distinct(case when CAST(start_time_1 AS TIME) <= '00:00:00' and CAST(end_time_1 AS TIME) >= '23:00:00' then id end)) as overnight_11pm_1am
from
(select id
, case
when cast(start_time as time) between '00:00:00' and '01:00:00'
then start_time - INTERVAL '01:00' HOUR TO MINUTE
else start_time
end as start_time_1
,case
when cast(end_timeas time) between '00:00:00' and '01:00:00'
then end_time - INTERVAL '01:00' HOUR TO MINUTE
else end_time
end as end_time_1
from table
where start_time >= '2021-01-01'
and start_time < '2021-01-04'
)
group by date_active
Out of ideas.
Im a beginner with SQL and need help to get some transactions in our WMS between 00.00.00 and 06.00.00 but can't make it work.
This is how far I have come,
SELECT cast(datreg as time) [time], logguser, l16lcode, partno, l16qty, datreg
FROM L16T3
WHERE datreg > '0000-00-00 00:00:00'
AND datreg < '9999-99-99 06:00:00'
AND L16T3.l16lcode = 2
I dont know what to write to get transactions only between 24.00-06.00
(Using SQL Server 2012)
Best Regards
Try this condition:
WHERE DATEPART(hour, datreg) BETWEEN 0 AND 5 OR
(DATEPART(hour, datreg) = 6 AND DATEPART(minute, datreg) = 0 AND DATEPART(second, datreg) = 0)
I would suggest:
SELECT cast(datreg as time) as [time], logguser, l16lcode, partno, l16qty, datreg
FROM L16T3 l
WHERE CONVERT(time, l.datreg) >= '00:00:00' AND
CONVERT(time, l.datreg) < '06:00:00' AND
l.l16lcode = 2;
You can also use the hours:
WHERE DATEPART(hour, l.datreg) >= 0 AND
DATEPART(hour, l.datreg) < 6 AND
l.l16lcode = 2;
However, this does not generalize so easily if, say, the second time were 06:30:00.
Something lie this perhaps:
SELECT IIF(CONVERT(TIME, GETDATE()) BETWEEN '00:00:00' AND '23:59:59','TRUE','FALSE');
Try the above query in SQLFiddle
In your case it would be something like this:
SELECT cast(datreg as time) [time], logguser, l16lcode, partno, l16qty, datreg
FROM L16T3
WHERE CONVERT(TIME, datreg ) BETWEEN '00:00:00' AND '06:00:00'
AND L16T3.l16lcode = 2
I need to write an SQL query for the following scenario.
I am having start date as 2020-01-10 13:00:00.347 and end date as 2020-01-12 02:00:00.347, so I need data grouped as
Day Hours
---- -----
10-01-2020 11
11-01-2020 24
12-01-2020 2.30
which means 11 hours was for the first date and 24 hours in second day and 2.3 hours on 3rd day.
What will the most Efficient SQL query to fetch the data in the above-mentioned format? Thanks in advance.
You can use a recursive CTE to break the dates into ranges:
with recursive cte as (
select start_date as day_start,
(case when date(start_date) = date(end_date) then end_date else date(start_date) + interval 1 day end) as day_end,
end_date
from (select cast('2020-01-10 13:00:00.347' as datetime) as start_date,
cast('2020-01-12 02:00:00.347' as datetime) as end_date
) t
union all
select day_end,
(case when date(day_end) = date(end_date) then end_date else date(day_end) + interval 1 day end) as day_end,
end_date
from cte
where day_end <> end_date
)
select day_start, day_end,
timestampdiff(second, day_start, day_end) / (60 * 60)
from cte;
Here is a db<>fiddle.
EDIT:
In SQL Server, this looks like:
with cte as (
select start_date as day_start,
(case when cast(start_date as date) = cast(end_date as date) then end_date else dateadd(day, 1, cast(start_date as date)) end) as day_end,
end_date
from (select cast('2020-01-10 13:00:00.347' as datetime) as start_date,
cast('2020-01-12 02:00:00.347' as datetime) as end_date
) t
union all
select day_end,
(case when cast(day_end as date) = cast(end_date as date) then end_date else dateadd(day, 1, day_end) end) as day_end,
end_date
from cte
where day_end <> end_date
)
select day_start, day_end,
datediff(second, day_start, day_end) / (60.0 * 60)
from cte;
Here is this db<>fiddle.
As the OP has asked for the most effecient method, and rCTE's are known to perform poorly, a more efficient approach would be using a Tally.
This isn't anywhere near as easy to read for a beginner, however, does get the results you are after (with the exception of that 2020-01-12 has a value of 2.0 not 2.3, as your math is clearly wrong there):
CREATE TABLE dbo.YourTable (StartDate datetime,
EndDate datetime);
INSERT INTO dbo.YourTable (StartDate,
EndDate)
VALUES('2020-01-10T13:00:00.347','2020-01-12T02:00:00.347'),
('2020-01-14T17:24:41.243','2020-01-19T09:17:12.997');
GO
WITH N AS(
SELECT N
FROM (VALUES(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL),(NULL))N(N)),
Tally AS(
SELECT TOP(SELECT MAX(DATEDIFF(DAY, StartDate, EndDate)+1) FROM dbo.YourTable)
ROW_NUMBER() OVER (ORDER BY (SELECT NULL)) -1 AS I
FROM N N1, N N2, N N3), --1000 days enough?
Dates AS(
SELECT DATEADD(DAY, T.I,CONVERT(date,YT.StartDate)) AS [Date],
CASE WHEN T.I = 0 THEN YT.StartDate ELSE DATEADD(DAY, T.I,CONVERT(date,YT.StartDate)) END AS StartingDateTime,
CASE WHEN LEAD(T.I) OVER (PARTITION BY YT.StartDate ORDER BY T.I) IS NULL THEN YT.EndDate ELSE DATEADD(DAY, T.I+1,CONVERT(date,YT.StartDate)) END AS EndingDateTime
FROM Tally T
JOIN dbo.YourTable YT ON T.I <= DATEDIFF(DAY, YT.StartDate, YT.EndDate))
SELECT D.[Date],
(DATEDIFF(SECOND,D.StartingDateTime,D.EndingDateTime) * 1.0) / 60 / 60 AS [Hours]
FROM Dates D;
GO
DROP TABLE dbo.YourTable;
DB<>Fiddle
The problem is with range 'THREE', to count from 10 pm till 06 am next day, result to be in previous day, i have this query who give me wrong data report,
any solutions please.
select TRUNC (A.time)+06/24,
count (distinct B.code)as FOUR,
count(case when to_char(A.time,'HH24:MI:SS') between '06:00:00'
and '14:00:00'
then A.sn end) as ONE,
count(case when to_char(A.time,'HH24:MI:SS') between '14:00:00'
and '22:00:00'
then A.sn end) as TWO,
count(case when A.time between TO_DATE ('10:00:00 PM', 'hh:mi:ss AM')
and TO_DATE ('10:00:00 PM', 'hh:mi:ss AM')+6/24
then A.sn end) as THREE
from B
inner join A
on B.bol_id = A.bol_id
where B.group = '9'
and A.time between '01-JUN-18 06:00:00' and '25-JUN-18 06:00:00'
GROUP BY TRUNC (A.time)
i want structure be like this example
Your problem is in the GROUP BY TRUNC (A.time) - this says to start the window for each row/day at midnight, and end at 11:59 the following night. But you want it from 6am on the current day to 5:59 the next morning. So you want to GROUP BY TRUNC(A.time - 6/24) - that way 5:59 this morning will be counted as yesterday, and 5:59 tomorrow will be counted as today.
Then you can modify your case THREE to be:
count(case when to_char(A.time,'HH24:MI:SS') > '22:00:00'
or to_char(A.time,'HH24:MI:SS') < '06:00:00'
then A.sn end) as THREE
Give it a try and let us know if you have any issues.
select TRUNC(A.time-(6/24)),
count (distinct B.code)as FOUR,
count(case when to_char(A.time,'HH24:MI:SS') between '06:00:00'
and '14:00:00'
then A.sn end) as ONE,
count(case when to_char(A.time,'HH24:MI:SS') between '14:00:00'
and '22:00:00'
then A.sn end) as TWO,
count(case when to_char(A.time,'HH24:MI:SS') > '22:00:00'
or to_char(A.time,'HH24:MI:SS') < '06:00:00'
then A.sn end) as THREE
from B
inner join A
on B.bol_id = A.bol_id
where B.group = '9'
and A.time between '01-JUN-18 06:00:00' and '25-JUN-18 06:00:00'
GROUP BY TRUNC(A.time-(6/24))
You might also want to change your cases from between to > and <=. between X and Y includes both end values, so any events happening at precisely 2 PM would be double-counted as both ONE and TWO.
I am trying to get number of transactions within the week given start date and end date.The below query works fine for one day 2011-10-14
SELECT COUNT(operationId) AS trans
FROM hwfg_t_Tracking
WHERE hitTime BETWEEN '2011-10-14 00:00:00' AND '2011-10-14 23:59:59.99'
GO
How can I get the count on operationId where hitTime between 14,13,12,11,10,9,8(1 week) with the single SELECT statement. Like number of transactions for 2011-10-14 as a column, 2011-10-13 as another column and so on
Try the following query for one row per day in your specified range:
SELECT cast(hitTime AS date) AS mydate, COUNT(operationId) AS trans
FROM hwfg_t_Tracking
WHERE hitTime >= '2011-10-14 00:00:00' AND hitTime < '2011-10-21 00:00:00'
GROUP BY cast(hitTime AS date)
Or, if you want them all in one row:
SELECT COUNT(*) AS total_sum
,COUNT(CASE WHEN cast(dt As date) = '2011-10-14' THEN 1 ELSE NULL END) AS day14
,COUNT(CASE WHEN cast(dt As date) = '2011-10-15' THEN 1 ELSE NULL END) AS day15
,COUNT(CASE WHEN cast(dt As date) = '2011-10-16' THEN 1 ELSE NULL END) AS day16
-- etc.
FROM hwfg_t_Tracking
WHERE hitTime >= '2011-10-14 00:00:00' AND hitTime < '2011-10-21 00:00:00'