SQL query to aggregate result from child table - sql-server

I need to join 4 table and display records in my application
route1
-------------------------
| ID | MODE | SCH DATE |
| 1 | T | 1/12019 |
| 2 | T | 2/12019 |
| 3 | T | 2/12019 |
--------------------------
Stop2
----------------------------
| ID | routeID | LocationID |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 1 | 3 |
| 4 | 2 | 4 |
| 5 | 2 | 5 |
| 6 | 3 | 6 |
-----------------------------
StopOrder2
----------------------------
| ID | StopID | Wight |
| 1 | 1 | 100 |
| 2 | 1 | 2 |
| 3 | 2 | 3 |
| 4 | 2 | 1 |
| 5 | 3 | 2 |
| 6 | 3 | 3 |
| 7 | 4 | 2 |
| 8 | 4 | 3 |
| 9 | 5 | 2 |
| 10 | 5 | 3 |
| 11 | 6 | 2 |
| 12 | 6 | 3 |
-----------------------------
Location
| LocationID | Name, City, Zip
| 1 | name1,city1 1111
| 2 | name2,city2 2222
| 3 | name3,city3 333
-----------------------------
I want final result with each route have how many records and how many orders and sum of all order wight
-----------------------------------------
| RouteID | MODE | SCH DATE |No Of Stop |LastLocatioID|OrderCount|
| 1 | T | 1/12019 | 3 | 3 | 6 |
| 2 | T | 2/12019 | 2 | 5 | 4 |
| 3 | T | 2/12019 | 1 | 6 | 2 |
How can I write the SQL query I need?

All you need is a simple group by:
SELECT
r.ID AS RouteID,
r.MODE,
r.[SCH DATE],
COUNT(s.ID) AS [No Of Stop],
MAX(s.LocationID) AS [LastLocationID],
COUNT(o.ID) AS OrderCount
FROM
#route1 r
INNER JOIN #Stop2 s
ON r.ID = s.routeID
INNER JOIN #StopOrder2 o
ON s.ID = o.StopID
GROUP BY
r.ID,
r.MODE,
r.[SCH DATE]
Output:

Related

SQL I want to figure out how to get sales 10 days for each product and within each group

I have a SQL Server table T1 that has orders by product_id, brand, and size for each day.
T1:
+------------+-------+------+----------+--------+
| product_id | Brand | Size | Date | Orders |
+------------+-------+------+----------+--------+
| 1 | 1 | 11 | 10/18/18 | 1 |
| 1 | 1 | 6 | 10/18/18 | 2 |
| 1 | 1 | 10 | 10/18/18 | 1 |
| 1 | 1 | 7 | 10/18/18 | 3 |
| 1 | 1 | 8.5 | 10/18/18 | 5 |
| 1 | 1 | 9.5 | 10/18/18 | 2 |
| 2 | 1 | 8 | 10/19/18 | 3 |
| 2 | 1 | 7 | 10/19/18 | 6 |
| 2 | 1 | 9 | 10/19/18 | 2 |
| 3 | 2 | 5 | 10/19/18 | 23 |
| 3 | 2 | 6 | 10/19/18 | 6 |
| 3 | 2 | 10 | 10/19/18 | 7 |
+------------+-------+------+----------+--------+
I also have a table, T2, that has the launch date for each product_id. A product_id may have more than one launch dates, signifying it is "restocked".
T2:
+------------+-------------+
| product_id | launch_date |
+------------+-------------+
| 1 | 8/18/18 |
| 1 | 10/18/18 |
| 2 | 10/18/18 |
| 3 | 4/18/18 |
+------------+-------------+
My goal is to create a table that is just the first 10 days of orders in each launch date (for each product_id, brand, and size). So if launch date for product 1 is 8/18/18 and 10/18/18, then I want the daily orders from 8/18/18 to 8/28/18, and from 10/18/18 to 10/28/18.
How would I go about creating this table?
Example output:
+------------+-------+------+----------+--------+
| product_id | Brand | Size | Date | Orders |
+------------+-------+------+----------+--------+
| 1 | 1 | 11 | 10/18/18 | 1 |
| 1 | 1 | 6 | 10/18/18 | 2 |
| 1 | 1 | 10 | 10/18/18 | 1 |
| 1 | 1 | 7 | 10/18/18 | 3 |
| 1 | 1 | 8.5 | 10/18/18 | 5 |
| 1 | 1 | 9.5 | 10/18/18 | 2 |
| … | | | | |
| 1 | 1 | 11 | 10/22/18 | 4 |
| 1 | 1 | 6 | 10/22/18 | 6 |
| 1 | 1 | 10 | 10/22/18 | 2 |
| 1 | 1 | 7 | 10/22/18 | 2 |
| 1 | 1 | 8.5 | 10/22/18 | 2 |
| 1 | 1 | 9.5 | 10/22/18 | 5 |
| … | | | | |
| 1 | 1 | 11 | 10/28/18 | 7 |
| 1 | 1 | 6 | 10/28/18 | 4 |
| 1 | 1 | 10 | 10/28/18 | 2 |
| 1 | 1 | 7 | 10/28/18 | 2 |
| 1 | 1 | 8.5 | 10/28/18 | 8 |
| 1 | 1 | 9.5 | 10/28/18 | 7 |
| … | | | | |
| 2 | 1 | 8 | 10/19/18 | 3 |
| 2 | 1 | 7 | 10/19/18 | 6 |
| 2 | 1 | 9 | 10/19/18 | 2 |
| 3 | 2 | 5 | 10/19/18 | 23 |
| 3 | 2 | 6 | 10/19/18 | 6 |
| 3 | 2 | 10 | 10/19/18 | 7 |
+------------+-------+------+----------+--------+
Thank you!
EDIT: including what I have tried so far:
My thought process is to try to create to join the launch_date and then create a column that is the number of days between the launch date and the Date of order. Then I can just filter for WHERE that column is less than or equal to 10.
This is the query I am using:
with temp as (
select
t1.product_id, t1.brand, t1.size, t1.date, t1.orders, t2.launch_date
from t1
left join t2 on t1.product_id = t2.product_id and t1.order_date = t2.order_date
)
select product_id,
brand,
size,
size,
date,
orders,
launch_date
from temp
;
In order for my reasoning to work, I would need to forward-fill the launch_date wherever it is null. I am not sure how to accomplish this. Here is the output I have so far:
+------------+-------+------+----------+--------+-------------+
| product_id | Brand | Size | Date | Orders | launch_date |
+------------+-------+------+----------+--------+-------------+
| 1 | 1 | 11 | 10/18/18 | 1 | 10/18/18 |
| 1 | 1 | 6 | 10/18/18 | 2 | 10/18/18 |
| 1 | 1 | 10 | 10/18/18 | 1 | 10/18/18 |
| 1 | 1 | 7 | 10/18/18 | 3 | 10/18/18 |
| 1 | 1 | 8.5 | 10/18/18 | 5 | 10/18/18 |
| 1 | 1 | 9.5 | 10/18/18 | 2 | 10/18/18 |
| … | | | | | |
| 1 | 1 | 11 | 10/22/18 | 4 | NULL |
| 1 | 1 | 6 | 10/22/18 | 6 | NULL |
| 1 | 1 | 10 | 10/22/18 | 2 | NULL |
| 1 | 1 | 7 | 10/22/18 | 2 | NULL |
| 1 | 1 | 8.5 | 10/22/18 | 2 | NULL |
| 1 | 1 | 9.5 | 10/22/18 | 5 | NULL |
| … | | | | | |
| 1 | 1 | 11 | 10/28/18 | 7 | NULL |
| 1 | 1 | 6 | 10/28/18 | 4 | NULL |
| 1 | 1 | 10 | 10/28/18 | 2 | NULL |
| 1 | 1 | 7 | 10/28/18 | 2 | NULL |
| 1 | 1 | 8.5 | 10/28/18 | 8 | NULL |
| 1 | 1 | 9.5 | 10/28/18 | 7 | NULL |
| … | | | | | |
| 2 | 1 | 8 | 10/19/18 | 3 | 10/18/18 |
| 2 | 1 | 7 | 10/19/18 | 6 | 10/18/18 |
| 2 | 1 | 9 | 10/19/18 | 2 | 10/18/18 |
| 3 | 2 | 5 | 10/19/18 | 23 | 10/18/18 |
| 3 | 2 | 6 | 10/19/18 | 6 | 10/18/18 |
| 3 | 2 | 10 | 10/19/18 | 7 | 10/18/18 |
+------------+-------+------+----------+--------+-------------+
If I can forward-fill the launch_date wherever it is NULL to be the most recent launch_date of that product_id, then I would be able to create a column to subtract the dates.

How to hide duplicate rows and display 4 count texts in 4 columns

I want to hide duplicate rows based on 2 columns (row,type)
In the status column I have 4 types of text
Enable,Disable,Run,End
Also 4 extra columns for these 4 texts
The number of each text based on that 2 columns is displayed in the corresponding column
I want to convert from :
|--------------------------------|
| id | row |value | type |status |
|--------------------------------|
| 1 | a | a | a |Enable |
| 2 | a | a | a |Disable|
| 3 | a | a | a |Run |
| 4 | a | a | a |End |
| 5 | a | a | a |End |
| |
| 6 | a | a | b |Enable |
| 7 | a | a | b |Run |
| |
| 8 | b | a | b |Enable |
| 9 | b | a | b |Disable|
| |
| 10 | b | a | c |Run |
| 11 | b | a | c |End |
| 12 | b | a | c |End |
| |
| 13 | c | a | a |Enable |
| 14 | c | a | a |Run |
|--------------------------------|
to :
|---------------------------------------------------------------|
| id | row |value | type |status |number |Enable|Disable|Run|End|
|---------------------------------------------------------------|
| 1 | a | a | a |Enable | 5 | 1 | 1 | 1 | 2 |
| 2 | a | a | b |Enable | 2 | 1 | 0 | 1 | 0 |
| 3 | b | a | b |Enable | 2 | 1 | 1 | 0 | 0 |
| 4 | b | a | c |Run | 3 | 0 | 0 | 1 | 2 |
| 5 | c | a | a |Enable | 2 | 1 | 0 | 1 | 0 |
|---------------------------------------------------------------|
my query :
SELECT
ROW_NUMBER() OVER(order by min(id)) AS 'id'
, row
, MIN(value) AS 'value'
, type
, MIN(status) AS 'status'
, COUNT(*) AS'number'
, (SELECT COUNT(1) FROM Work WHERE status LIKE 'Enable' ) AS 'Enable'
, (SELECT COUNT(1) FROM Work WHERE status LIKE 'Disable' ) AS 'Disable'
, (SELECT COUNT(1) FROM Work WHERE status LIKE'Run') AS 'Run'
, (SELECT COUNT(1) FROM Work WHERE status LIKE 'End') AS 'End'
FROM Work AS w
WHERE type ='a'
GROUP BY row,type
ORDER BY MIN(id)
But with this query the output is :
|---------------------------------------------------------------|
| id | row |value | type |status |number |Enable|Disable|Run|End|
|---------------------------------------------------------------|
| 1 | a | a | a |Enable | 5 | 1 | 1 | 1 | 2 |
| 2 | a | a | b |Enable | 2 | 1 | 1 | 1 | 2 |
| 3 | b | a | b |Enable | 2 | 1 | 1 | 1 | 2 |
| 4 | b | a | c |Run | 3 | 1 | 1 | 1 | 2 |
| 5 | c | a | a |Enable | 2 | 1 | 1 | 1 | 2 |
|---------------------------------------------------------------|
There is missing where part in every select count(*)... .
...
,(select count(*) from Work w2 where status like 'Enable' and w.row = w2.row and w.type = w2.type ) as 'Enable'
...

Adding a count column in SQL Server for groups of records

I am trying to update an existing table with an individual count of the record on each row in a count column.
The table has the following columns that need to be incremented:
MBR_NO, CLAIM_N0, Effective_Dt, incr_count
So a sample might look like this before the run:
MBR_NO | CLAIM_N0 | Effective_Dt | incr_count |
-------+----------+----------------+------------+
1 | 2 | 1/1/2015 | NULL |
1 | 4 | 5/5/2015 | NULL |
1 | 5 | 6/7/2016 | NULL |
1 | 7 | 8/7/2016 | NULL |
2 | 2 | 4/3/2015 | NULL |
2 | 5 | 5/21/2015 | NULL |
3 | 8 | 3/27/2015 | NULL |
I want to count by MBR_NO and update the Incr_count to look like this:
MBR_NO | CLAIM_N0 | Effective_Dt | incr_count |
-------+----------+----------------+------------+
1 | 2 | 1/1/2015 | 1 |
1 | 4 | 5/5/2015 | 2 |
1 | 5 | 6/7/2016 | 3 |
1 | 7 | 8/7/2016 | 4 |
2 | 2 | 4/3/2015 | 1 |
2 | 5 | 5/21/2015 | 2 |
3 | 8 | 3/27/2015 | 1 |
I need to change that filed for processing later on.
I know this is not that complex but It seemed that the other topics offered solutions that don't incrementally update. Any help would be appreciated.
You could just do this in a query with
ROW_NUMBER() OVER (PARTITION BY MBR_NO ORDER BY Effective_DT).
but does it matter if the number changes? i.e. in your example if you had
MBR_NO EffectiveDate RowNumber
------------------------------------
2 1/1/2017 1
2 5/1/2017 2
but if you inserted a row with an effective date of say 3/1/2017 it would change the row number for the 5/1/2017 row i.e.
MBR_NO EffectiveDate RowNumber
------------------------------------
2 1/1/2017 1
2 3/1/2017 2
2 5/1/2017 3
You can query as below:
Select MBR_NO, CLAIM_N0, Effective_Dt,
incr_count = count(MBR_NO) over(Partition by MBR_NO order by Effective_Dt)
from yourtable
Output as below:
+--------+----------+--------------+------------+
| MBR_NO | CLAIM_N0 | Effective_Dt | incr_count |
+--------+----------+--------------+------------+
| 1 | 2 | 2015-01-01 | 1 |
| 1 | 4 | 2015-05-05 | 2 |
| 1 | 5 | 2016-06-07 | 3 |
| 1 | 7 | 2016-08-07 | 4 |
| 2 | 2 | 2015-04-03 | 1 |
| 2 | 5 | 2015-05-21 | 2 |
| 3 | 8 | 2015-03-27 | 1 |
+--------+----------+--------------+------------+

Row number by 3 distincts fields in SQL Server

I have this table:
| RecordLocator | DepartureStation | ArrivalStation | JourneyNumber | SegmentNumber | LegNumber | FlightNumber |
|---------------|------------------|----------------|---------------|---------------|-----------|--------------|
| DADABC | MAO | GRU | 2 | 1 | 1 | 1421 |
| CEDLDA | MAO | STM | 1 | 2 | 1 | 1643 |
| CEDLDA | GRU | MAO | 1 | 1 | 1 | 1640 |
| DADABC | GRU | FLN | 1 | 1 | 1 | 1848 |
| CEDLDA | BEL | SLZ | 1 | 2 | 3 | 1643 |
| DADABC | GIG | FOR | 1 | 2 | 3 | 1154 |
| CEDLDA | SLZ | FOR | 1 | 2 | 4 | 1680 |
| CEDLDA | FOR | REC | 1 | 2 | 5 | 1680 |
| DADABC | FOR | MAO | 1 | 2 | 4 | 1982 |
| CEDLDA | REC | SSA | 1 | 2 | 6 | 1680 |
| CEDLDA | STM | BEL | 1 | 2 | 2 | 1643 |
| DADABC | POA | GIG | 1 | 2 | 2 | 1201 |
| CEDLDA | SSA | GRU | 1 | 3 | 1 | 1817 |
| DADABC | FLN | POA | 1 | 2 | 1 | 1201 |
I want add a new column row number based on JourneyNumber, SegmentNumber and LegNumber, order by RecordLocator, for obtain this result:
| RecordLocator | DepartureStation | ArrivalStation | JourneyNumber | SegmentNumber | LegNumber | FlightNumber | rowNum |
|---------------|------------------|----------------|---------------|---------------|-----------|--------------|--------|
| CEDLDA | GRU | MAO | 1 | 1 | 1 | 1640 | 1 |
| CEDLDA | MAO | STM | 1 | 2 | 1 | 1643 | 2 |
| CEDLDA | STM | BEL | 1 | 2 | 2 | 1643 | 3 |
| CEDLDA | BEL | SLZ | 1 | 2 | 3 | 1643 | 4 |
| CEDLDA | SLZ | FOR | 1 | 2 | 4 | 1680 | 5 |
| CEDLDA | FOR | REC | 1 | 2 | 5 | 1680 | 6 |
| CEDLDA | REC | SSA | 1 | 2 | 6 | 1680 | 7 |
| CEDLDA | SSA | GRU | 1 | 3 | 1 | 1817 | 8 |
| DADABC | GRU | FLN | 1 | 1 | 1 | 1848 | 1 |
| DADABC | FLN | POA | 1 | 2 | 1 | 1201 | 2 |
| DADABC | POA | GIG | 1 | 2 | 2 | 1201 | 3 |
| DADABC | GIG | FOR | 1 | 2 | 3 | 1154 | 4 |
| DADABC | FOR | MAO | 1 | 2 | 4 | 1982 | 5 |
| DADABC | MAO | GRU | 2 | 1 | 1 | 1421 | 6 |
I tried this query:
SELECT
RecordLocator,
DepartureStation, ArrivalStation,
JourneyNumber, SegmentNumber,
LegNumber, FlightNumber,
(SELECT ((P.JourneyNumber + P.SegmentNumber + P.LegNumber))
FROM PAX P2
WHERE P2.RecordLocator = P.RecordLocator
AND P2.DepartureStation = P.DepartureStation
AND P2.ArrivalStation = P.ArrivalStation
AND P2.JourneyNumber = P.JourneyNumber
AND P2.SegmentNumber = P.SegmentNumber
AND P2.LegNumber = P.LegNumber
AND P2.FlightNumber = P.FlightNumber) AS rowNum
FROM
PAX P
I'm trying sum the columns JourneyNumber, SegmentNumber and LegNumber but does not work, i belive best way to do, is based on Recordlocator define a "weight" for the columns JourneyNumber > SegmentNumber > LegNumber, but i don't know how implement it.
In C# I know how to do it, using align for:
// First `for` - Journey
for(int i = 0; i < Journey.Count(); i++)
{
// Second `for` - Segment
for(int j = 0; j < Segment.Count(); j++)
{
// Third `for` - Leg
for(int k = 0; k < Leg.Count(); k++)
{
result = i + j + k;
}
}
}
Basically, breaking down your question into its parts, you want to re-start numbering for each RecordLocator, then you order it by the 3 fields you wanted in ascending order.
Overall, that's the idea of the ROW_NUMBER() which allows for ordering your records with a partition set for RecordLocator to re-start the numbering as needed. So, something like this should do it:
ROW_NUMBER() OVER(PARTITION BY RecordLocator ORDER BY JourneyNumber, SegmentNumber, LegNumber)
And your final SQL, therefore, becoming:
SELECT RecordLocator
, DepartureStation
, ArrivalStation
, JourneyNumber
, SegmentNumber
, LegNumber
, FlightNumber
, ROW_NUMBER() OVER(PARTITION BY RecordLocator ORDER BY JourneyNumber, SegmentNumber, LegNumber) AS rowNum
FROM PAX P
Hope this does the trick!

Add one with same foreign key at row sql server

I have a problem on sql server.
How to get running number from foreign key in one time select data from table?
example :
I have one table such as
-----------------
| id | pid | desc |
-----------------
| 1 | 1 | a |
| 2 | 1 | b |
| 3 | 1 | c |
| 4 | 2 | d |
| 5 | 2 | e |
| 6 | 2 | f |
| 7 | 2 | g |
| 8 | 3 | h |
| 9 | 3 | i |
| 10 | 1 | j |
| 11 | 1 | k |
-----------------
I want to get result as below
------------------------
| id | pid | desc | rec |
------------------------
| 1 | 1 | a | 1 |
| 2 | 1 | b | 2 |
| 3 | 1 | c | 3 |
| 4 | 2 | d | 1 |
| 5 | 2 | e | 2 |
| 6 | 2 | f | 3 |
| 7 | 2 | g | 4 |
| 8 | 3 | h | 1 |
| 9 | 3 | i | 2 |
| 10 | 1 | j | 4 |
| 11 | 1 | K | 5 |
------------------------
In above tables foreign key ('pid') Column has values 1 to 3 in different row numbers.
I tried to get the running number from each 'pid' field name.
I havn't found any way to do this,
Can I do that? Can some one help me? am still newbie at sql server
Try this
SELECT
id,
pid,
[desc],
Row_Number() OVER (PARTITION BY pid ORDER BY id) AS rec
FROM <yourtable>
ORDER BY id
You can use Ranking function in SQL Server 2005+ to accomplish that,
So here is your query
Select Row_Number() over (partition by pid order by id) as rec , * from Table

Resources