如何用SQL计算仓库无物品出入最长时段?现有写法是否正确?
Hey there! Let's tackle your two SQL questions step by step—they're great ones, especially that second one which trips up a lot of folks.
First, let's clarify what we mean here. If you're looking to calculate the maximum length of time between two specific fixed dates (e.g., from '2024-01-01' to '2024-06-30'), that's straightforward with date difference functions—though syntax varies a bit by SQL dialect:
For MySQL/MariaDB: Use
DATEDIFFfor days, orTIMESTAMPDIFFfor more granular units:-- Get days between two dates SELECT DATEDIFF('2024-06-30', '2024-01-01') AS max_interval_days; -- Get hours between two timestamps SELECT TIMESTAMPDIFF(HOUR, '2024-01-01 00:00:00', '2024-06-30 23:59:59') AS max_interval_hours;For PostgreSQL: Use the
-operator directly for interval types, orDATE_PARTto extract specific units:-- Get full interval SELECT '2024-06-30'::DATE - '2024-01-01'::DATE AS max_interval; -- Extract total days SELECT DATE_PART('day', '2024-06-30'::DATE - '2024-01-01'::DATE) AS max_interval_days;For SQL Server: Use
DATEDIFF:SELECT DATEDIFF(DAY, '2024-01-01', '2024-06-30') AS max_interval_days;
If you meant finding the longest continuous window within those two dates where some condition holds (e.g., no warehouse activity), you'll need a similar approach to what we'll use for your second question—just filter events to fall within your target date range first.
Your current query select MAX(OutTime-InTime) from Warehouse where OutTime is not null is actually calculating the longest time a single item stayed in the warehouse—not the gaps when no items were being moved in or out. That's a super common mix-up!
To find the longest idle period (no InTime or OutTime events), we need to look at the gaps between consecutive activity timestamps. Here's a clean, dialect-flexible way to do it:
Example Query Using CTEs
WITH all_events AS ( -- Combine all InTime and OutTime into a single list of activity timestamps SELECT InTime AS event_time FROM Warehouse WHERE InTime IS NOT NULL UNION ALL SELECT OutTime AS event_time FROM Warehouse WHERE OutTime IS NOT NULL ), ordered_events AS ( -- Order events and get the timestamp of the previous activity SELECT event_time, LAG(event_time) OVER (ORDER BY event_time) AS prev_event_time FROM all_events ), calculated_gaps AS ( -- Compute duration of each gap between consecutive events SELECT event_time - prev_event_time AS gap_between_events FROM ordered_events WHERE prev_event_time IS NOT NULL -- Skip the first event (no previous timestamp) -- Add gaps for before the first event and after the last event (if needed) UNION ALL SELECT (SELECT MIN(event_time) FROM all_events) - '2020-01-01'::DATE -- Replace with warehouse launch date UNION ALL SELECT CURRENT_TIMESTAMP - (SELECT MAX(event_time) FROM all_events) ) -- Grab the largest gap from all possibilities SELECT MAX(gap_between_events) AS longest_idle_period FROM calculated_gaps;
Key Adjustments For Your SQL Dialect:
- MySQL/MariaDB: Replace
event_time - prev_event_timewithTIMESTAMPDIFF(HOUR, prev_event_time, event_time)(orSECOND/DAYfor different units) to get a numeric duration. - SQL Server: Use
DATEDIFF(HOUR, prev_event_time, event_time)orDATEDIFF_BIGfor longer intervals. - If you don't care about idle time before the first item arrived or after the last item left, you can remove those two
UNION ALLlines.
This approach focuses on the gaps between warehouse activity, which is exactly what you're trying to measure!
内容的提问来源于stack exchange,提问作者Lukasz

