My goal here is to take a list of two corresponding store numbers and provide an output similar to:
Ultimate goal: produce a list of closest stores by travel time and distance based on source data of 2 rows per zip9 where each row is the travel time in distance, and in time, to a store in question.
The result is that each zip code has 2 stores to choose from, and the requirement is being able to return one row with both options.
+-----------+---------------+---------------------+-------------------+-------------------------+
| zip | Shortest_time | Shortest_time_store | Shortest_distance | Shortest_distance_store |
+-----------+---------------+---------------------+-------------------+-------------------------+
| 70011134 | 38.7035 | 75 | 21.3124 | 115 |
| 70011186 | 38.4841 | 75 | 21.4144 | 115 |
| 70011207 | 39.1567 | 75 | 21.1826 | 115 |
| 100013232 | 22.976 | 145 | 9.5031 | 115 |
| 112075140 | 21.888 | 145 | 7.3705 | 115 |
+-----------+---------------+---------------------+-------------------+-------------------------+
Original dataset
+---------------+--------------------------+-----------------------+------------------+
| CORRECTED_ZIP | SourceOrganizationNumber | Travel Time (Minutes) | Distance (Miles) |
+---------------+--------------------------+-----------------------+------------------+
| 70011134 | 75 | 38.7035 | 26.8628 |
| 70011134 | 115 | 39.3969 | 21.3124 |
| 70011186 | 75 | 38.4841 | 26.7609 |
| 70011186 | 115 | 39.6389 | 21.4144 |
| 70011207 | 75 | 39.1567 | 31.2771 |
| 70011207 | 115 | 39.188 | 21.1826 |
| 100013232 | 115 | 28.6561 | 9.50311 |
| 100013232 | 145 | 22.976 | 10.0307 |
| 112075140 | 115 | 36.1803 | 7.37053 |
| 112075140 | 145 | 21.888 | 9.50123 |
+---------------+--------------------------+-----------------------+------------------+
Dataset after I've modified it with this query:
SELECT TOP 1000 [corrected_zip]
, TRY_CONVERT( DECIMAL(18, 4), ROUND([Travel Time (Minutes)], 4)) AS [Unit of Measurement]
, [SourceOrganizationNumber]
, 'Time' AS [Type]
FROM [db].[dbo].[my_table_A] [tt]
WHERE [tt].[CORRECTED_ZIP] IN('070011134', '070011186', '070011207', '112075140', '100013232')
AND [Travel Time (Minutes)] IN
(
SELECT MIN([Travel Time (Minutes)])
FROM [db].[dbo].[my_table_A]
WHERE [CORRECTED_ZIP] = [tt].[CORRECTED_ZIP]
GROUP BY [CORRECTED_ZIP]
)
UNION ALL
SELECT TOP 1000 [corrected_zip]
, TRY_CONVERT( DECIMAL(18, 4), ROUND([Distance (Miles)], 4))
, [SourceOrganizationNumber]
, 'Distance'
FROM [db].[dbo].[my_table_A] [tt]
WHERE [tt].[CORRECTED_ZIP] IN('070011134', '070011186', '070011207', '112075140', '100013232')
AND [Distance (Miles)] IN
(
SELECT MIN([Distance (Miles)])
FROM [db].[dbo].[my_table_A]
WHERE [CORRECTED_ZIP] = [tt].[CORRECTED_ZIP]
GROUP BY [CORRECTED_ZIP]
)
ORDER BY [CORRECTED_ZIP];
+---------------+---------------------+--------------------------+----------+
| corrected_zip | Unit of Measurement | SourceOrganizationNumber | Type |
+---------------+---------------------+--------------------------+----------+
| 70011134 | 38.7035 | 75 | Time |
| 70011134 | 21.3124 | 115 | Distance |
| 70011186 | 21.4144 | 115 | Distance |
| 70011186 | 38.4841 | 75 | Time |
| 70011207 | 39.1567 | 75 | Time |
| 70011207 | 21.1826 | 115 | Distance |
| 100013232 | 9.5031 | 115 | Distance |
| 100013232 | 22.976 | 145 | Time |
| 112075140 | 21.888 | 145 | Time |
| 112075140 | 7.3705 | 115 | Distance |
+---------------+---------------------+--------------------------+----------+
Data after I attempted to pivot it
+---------------+--------------------------+----------+---------+
| corrected_zip | SourceOrganizationNumber | Distance | Time |
+---------------+--------------------------+----------+---------+
| 070011134 | 115 | 21.3124 | NULL |
| 070011134 | 75 | NULL | 38.7035 |
| 070011186 | 115 | 21.4144 | NULL |
| 070011186 | 75 | NULL | 38.4841 |
| 070011207 | 115 | 21.1826 | NULL |
| 070011207 | 75 | NULL | 39.1567 |
| 100013232 | 115 | 9.5031 | NULL |
| 100013232 | 145 | NULL | 22.9760 |
| 112075140 | 115 | 7.3705 | NULL |
| 112075140 | 145 | NULL | 21.8880 |
+---------------+--------------------------+----------+---------+
It seems like my issue is picking the correct store ID as opposed to grouping by store ID?
You can use row_number() twice in a subquery(once to rank by time, another by distance), and then do conditional aggregation in the outer query:
select
corrected_zip,
min(travel_time) shortest_time,
min(case when rnt = 1 then source_organization_number end) shortest_time_store,
min(distance) shortest_distance,
min(case when rnd = 1 then source_organization_number end) shortest_distance_store
from (
select
t.*,
row_number() over(partition by corrected_zip order by travel_time) rnt,
row_number() over(partition by corrected_zip order by distance) rnd
from mytable t
) t
group by corrected_zip
I have following SQL Server table ITEM:
+------------+-----------+------+--------+-----------+------------+
| Date | item_code | name | in/out | total_qty | SortNumber |
+------------+-----------+------+--------+-----------+------------+
| 08/07/2019 | 001 | A | -50 | 100 | 8 |
| 07/07/2019 | 001 | A | 50 | 100 | 7 |
| 06/07/2019 | 003 | C | 25 | 25 | 6 |
| 05/07/2019 | 001 | A | 50 | 50 | 5 |
| 04/07/2019 | 002 | B | 100 | 200 | 4 |
| 03/07/2019 | 003 | C | -25 | 0 | 3 |
| 02/07/2019 | 003 | C | 25 | 25 | 2 |
| 01/07/2019 | 002 | B | 100 | 100 | 1 |
+------------+-----------+------+--------+-----------+------------+
I've tried:
select itemcode, max(Sort_Number)
from ITEM
group by item_code
order by item_code asc
but I want result:
+---------------------+-----------+------------------+
| Distinct(item_code) | Total_qty | Max(Sort_Number) |
+---------------------+-----------+------------------+
| 001 | 100 | 8 |
| 002 | 200 | 4 |
| 003 | 25 | 6 |
+---------------------+-----------+------------------+
Can anyone help me?
The below query gives you the desired result -
With cteItem as
(
select item_code, total_qty, SortNumber,
Row_Number() over (partition by item_code order by SortNumber desc) maxSortNumber
from ITEM
)
select item_code, total_qty, SortNumber from cteItem where maxSortNumber = 1
just need to add max(sort_number) to your query
select item_code ,max(total_qty), max(sort_number)
from ITEM
group by item_code
order by item_code asc
i have a SQL that displays turnover, stock and other values for stores grouped by month. Logically, if there is no value for a month, the month doesn't appear. The target is that the empty month should appear and display "NULL" for the values. The empty months should range from the #FROM to the #TO parameter (201807 to 201907) in this case.
Before:
+-------+--------+----------+----------+-------+
| Store | Month | Incoming | Turnover | Stock |
+-------+--------+----------+----------+-------+
| 123 | 201810 | 5 | 4 | 1 |
| 123 | 201811 | 0 | 1 | 0 |
| 123 | 201901 | 25 | 5 | 20 |
| 123 | 201902 | 5 | 10 | 15 |
| 123 | 201903 | 8 | 9 | 14 |
| 123 | 201904 | 5 | 4 | 15 |
| 123 | 201905 | 10 | 5 | 20 |
+-------+--------+----------+----------+-------+
After:
+-------+--------+----------+----------+-------+
| Store | Month | Incoming | Turnover | Stock |
+-------+--------+----------+----------+-------+
| 123 | 201807 | NULL | NULL | NULL |
| 123 | 201808 | NULL | NULL | NULL |
| 123 | 201809 | NULL | NULL | NULL |
| 123 | 201810 | 5 | 4 | 1 |
| 123 | 201811 | 0 | 1 | 0 |
| 123 | 201812 | NULL | NULL | NULL |
| 123 | 201901 | 25 | 5 | 20 |
| 123 | 201902 | 5 | 10 | 15 |
| 123 | 201903 | 8 | 9 | 14 |
| 123 | 201904 | 5 | 4 | 15 |
| 123 | 201905 | 10 | 5 | 20 |
| 123 | 201906 | NULL | NULL | NULL |
| 123 | 201907 | NULL | NULL | NULL |
+-------+--------+----------+----------+-------+
Code Example: db<>fiddle
I have absolutely no idea how to solve this and will thank you in advance for your help! :)
You can try to use cte recursive make a calendar table, then do outer-join
;WITH CTE AS (
SELECT CAST(CAST(#FROM AS VARCHAR(10)) + '01' AS DATE) fromDt,
CAST(CAST(#TO AS VARCHAR(10)) + '01' AS DATE) toDt,
Store
FROM (SELECT DISTINCT Store FROM #Test) t1
UNION ALL
SELECT DATEADD(MONTH,1,fromDt),toDt,Store
FROM CTE
WHERE DATEADD(MONTH,1,fromDt) <= toDt
)
SELECT FORMAT(fromDt,'yyyyMM') Month,
c.Store,
t.Incoming,
t.Turnover,
t.Stock
FROM CTE c
LEFT JOIN #Test t on
c.fromDt = CAST(CAST(t.Month AS VARCHAR(10)) + '01' AS DATE)
and
c.Store = t.Store
sqlfiddle
I'm dipping my toes into SQL. I have the following table
+------+----+------+------+-------+
| Type | ID | QTY | Rate | Name |
+------+----+------+------+-------+
| B | 1 | 1000 | 21 | Jack |
| B | 2 | 2000 | 12 | Kevin |
| B | 1 | 3000 | 24 | Jack |
| B | 1 | 1000 | 23 | Jack |
| B | 3 | 200 | 13 | Mary |
| B | 2 | 3000 | 12 | Kevin |
| B | 4 | 4000 | 44 | Chris |
| B | 4 | 5000 | 43 | Chris |
| B | 3 | 1000 | 26 | Mary |
+------+----+------+------+-------+
I don't know how I would leverage Sum and Group by to achieve the following result.
+------+----+------+------+-------+------------+
| Type | ID | QTY | Rate | Name | Sum of QTY |
+------+----+------+------+-------+------------+
| B | 1 | 1000 | 21 | Jack | 5000 |
| B | 1 | 3000 | 24 | Jack | Null |
| B | 1 | 1000 | 23 | Jack | Null |
| B | 2 | 3000 | 12 | Kevin | 5000 |
| B | 2 | 3000 | 12 | Kevin | Null |
| B | 3 | 200 | 13 | Mary | 1200 |
| B | 3 | 1000 | 26 | Mary | Null |
| B | 4 | 4000 | 44 | Chris | 9000 |
| B | 4 | 5000 | 43 | Chris | Null |
+------+----+------+------+-------+------------+
Any help is appreciated!
You can use window function :
select t.*,
(case when row_number() over (partition by type, id order by name) = 1
then sum(qty) over (partition by type, id order by name)
end) as Sum_of_QTY
from table t;
I'm using SQL Server 2008 R2 and I have the following dataset:
+---------+--------------+--------------+----------+------------+------------+
| Dossier | refmouvement | refadmission | refunite | datedeb | datefin |
+---------+--------------+--------------+----------+------------+------------+
| P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 |
| P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 |
| P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 |
| P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 |
| P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 |
| P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 |
| P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 |
| P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 |
| P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 |
| P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 |
| P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 |
| P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 |
+---------+--------------+--------------+----------+------------+------------+
This dataset is ordered by datedeb, otherwise known as startdate.
As you can notice this is a contiguous dataset where datefin is equal to the next line's datedeb
I need to create an ID column that is going to give an unique ID based on the refunite and the datedeb columns like this:
+----+---------+--------------+--------------+----------+------------+------------+
| ID | Dossier | refmouvement | refadmission | refunite | datedeb | datefin |
+----+---------+--------------+--------------+----------+------------+------------+
| 1 | P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 |
| 1 | P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 |
| 2 | P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 |
| 3 | P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 |
| 3 | P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 |
| 3 | P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 |
| 3 | P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 |
| 4 | P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 |
| 5 | P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 |
| 5 | P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 |
| 6 | P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 |
| 7 | P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 |
+----+---------+--------------+--------------+----------+------------+------------+
I just can't wrap my head around a RANK(), ROW_NUMBER() or DENSE_RANK() function or a combination of that could achieve this, I have looked everywhere but I cannot find anything, maybe I'm not using the proper keywords but I just can't figure it out
Any help will be appreciated
Thanks.
Here's the code that I've tried so far:
SELECT
ROW_NUMBER() over(order by t1.[datedeb]) as [ID1],
dense_Rank() over(partition by t1.[refunite] order by t1.[datedeb]) as [ID2],
t1.[Dossier]
,t1.[refmouvement]
,t1.[refadmission]
,t1.[refunite]
,t1.[datedeb]
,t1.[datefin]
,t2.[refmouvement] as [prev_refmouvement]
,t2.refunite as prev_refunite
FROM [sometable] t1
LEFT OUTER JOIN [sometable] t2 /*self join*/
ON t2.datefin = t1.datedeb
AND t1.[refadmission] = t2.[refadmission]
ORDER BY
t1.[datedeb]
This is what it gives me :
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
| ID1 | ID2 | Dossier | refmouvement | refadmission | refunite | datedeb | datefin | prev_refmouvement | prev_refunite |
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
| 1 | 1 | P001234 | 2567 | 1234 | 227 | 2012-01-01 | 2012-01-02 | NULL | NULL |
| 2 | 2 | P001234 | 2568 | 1234 | 227 | 2012-01-02 | 2012-01-03 | 2567 | 227 |
| 3 | 1 | P001234 | 2569 | 1234 | 224 | 2012-01-03 | 2012-01-06 | 2568 | 227 |
| 4 | 1 | P001234 | 2570 | 1234 | 232 | 2012-01-06 | 2012-01-10 | 2569 | 224 |
| 5 | 2 | P001234 | 2571 | 1234 | 232 | 2012-01-10 | 2012-01-15 | 2570 | 232 |
| 6 | 3 | P001234 | 2572 | 1234 | 232 | 2012-01-15 | 2012-01-20 | 2571 | 232 |
| 7 | 4 | P001234 | 2573 | 1234 | 232 | 2012-01-20 | 2012-01-25 | 2572 | 232 |
| 8 | 2 | P001234 | 2574 | 1234 | 224 | 2012-01-25 | 2012-01-29 | 2573 | 232 |
| 9 | 3 | P001234 | 2575 | 1234 | 227 | 2012-01-29 | 2012-02-05 | 2574 | 224 |
| 10 | 4 | P001234 | 2576 | 1234 | 227 | 2012-02-05 | 2012-02-10 | 2575 | 227 |
| 11 | 5 | P001234 | 2577 | 1234 | 232 | 2012-02-10 | 2012-02-15 | 2576 | 227 |
| 12 | 1 | P001234 | 2578 | 1234 | 201 | 2012-02-15 | 2012-02-26 | 2577 | 232 |
+-----+-----+---------+--------------+--------------+----------+------------+------------+-------------------+---------------+
Shaz
DECLARE #Results TABLE(
RowNum INT PRIMARY KEY,
refunite INT NOT NULL,
datedeb DATETIME NOT NULL
);
INSERT #Results (RowNum, refunite, datedeb)
SELECT ROW_NUMBER() OVER(ORDER BY datedeb) AS RowNum,
refunite,
datedeb
FROM dbo.MyTable;
WITH CTERecursive
AS (
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
1 AS Rnk -- Starting rank
FROM #Results crt
WHERE crt.RowNum = 1
UNION ALL
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
CASE WHEN prev.refunite = crt.refunite THEN prev.Rnk ELSE prev.Rnk + 1 END
FROM #Results crt INNER JOIN CTERecursive prev ON crt.RowNum = prev.RowNum + 1
)
SELECT *
FROM CTERecursive
-- OPTION(MAXRECURSION 1000); -- Uncomment this line if you change the number of recursion levels allowed (default 100)
Results:
RowNum refunite datedeb Rnk
----------- ----------- ----------------------- ---
1 227 2012-01-01 00:00:00.000 1
2 227 2012-01-02 00:00:00.000 1
3 224 2012-01-03 00:00:00.000 2
4 232 2012-01-06 00:00:00.000 3
5 232 2012-01-10 00:00:00.000 3
6 232 2012-01-15 00:00:00.000 3
7 232 2012-01-20 00:00:00.000 3
8 224 2012-01-25 00:00:00.000 4
9 227 2012-01-29 00:00:00.000 5
10 227 2012-02-05 00:00:00.000 5
11 232 2012-02-10 00:00:00.000 6
12 201 2012-02-15 00:00:00.000 7
You could, of course, have multiple tables in the WITH, eliminating the table variable.
Based on Bogdan Sahleans answer, you could rewrite like this:
WITH CTEHelper AS
(SELECT ROW_NUMBER() OVER(ORDER BY datedeb) AS RowNum,
refunite,
datedeb
FROM dbo.Sometable),
CTERecursive AS (
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
1 AS Id -- Starting rank
FROM CTEHelper crt
WHERE crt.RowNum = 1
UNION ALL
SELECT crt.RowNum,
crt.refunite,
crt.datedeb,
CASE WHEN prev.refunite = crt.refunite THEN prev.Id ELSE prev.Id + 1 END
FROM CTEHelper crt INNER JOIN CTERecursive prev ON crt.RowNum = prev.RowNum + 1
)
SELECT crt.id,
s.*
FROM CTERecursive crt
JOIN Sometable s ON s.refunite = crt.refunite AND s.datedeb = crt.datedeb
with sometable as (
select *
from (
values ('P001234', 2567, 1234, 227, cast('2012-01-01' as date), cast('2012-01-02' as date)),
('P001234', 2568, 1234, 227, cast('2012-01-02' as date), cast('2012-01-03' as date)),
('P001234', 2569, 1234, 224, cast('2012-01-03' as date), cast('2012-01-06' as date)),
('P001234', 2570, 1234, 232, cast('2012-01-06' as date), cast('2012-01-10' as date)),
('P001234', 2571, 1234, 232, cast('2012-01-10' as date), cast('2012-01-15' as date)),
('P001234', 2572, 1234, 232, cast('2012-01-15' as date), cast('2012-01-20' as date)),
('P001234', 2573, 1234, 232, cast('2012-01-20' as date), cast('2012-01-25' as date)),
('P001234', 2574, 1234, 224, cast('2012-01-25' as date), cast('2012-01-29' as date)),
('P001234', 2575, 1234, 227, cast('2012-01-29' as date), cast('2012-02-05' as date)),
('P001234', 2576, 1234, 227, cast('2012-02-05' as date), cast('2012-02-10' as date)),
('P001234', 2577, 1234, 232, cast('2012-02-10' as date), cast('2012-02-15' as date)),
('P001234', 2578, 1234, 201, cast('2012-02-15' as date), cast('2012-02-26' as date))
) t (Dossier, refmouvement, refadmission, refunite, datedeb, datefin)
), pos as (
select d.*, (case when d2.refunite is null then null
when d2.refunite != d.refunite then d2.datedeb
else d.datedeb end) as forward,
(case when d3.refunite is null then null
when d3.refunite != d.refunite then d3.datedeb
else d.datedeb end) as backward
from sometable d
left outer join sometable d2 on d.refadmission = d2.refadmission and d.datefin = d2.datedeb
left outer join sometable d3 on d.refadmission = d3.refadmission and d.datedeb = d3.datefin
)
select dense_rank() over (order by isnull((select min(datedeb)
from pos
where refadmission = t.refadmission
and refunite = t.refunite
and datedeb > t.datedeb
and datedeb = backward
and ((t.datedeb = t.backward and t.datedeb = t.forward)
or t.datedeb != t.backward or t.backward is null)
and datedeb != forward), datedeb)) as ID,
Dossier, refmouvement, refadmission, refunite, datedeb, datefin
from pos t
order by datedeb