I have these tables.
Main table
[key] [CategoryID]
AAAA 100
BBBB 100
CCCC 101
DDDD 102
EEEE 201
FFFF 202
GGGG 202
etc.
Category lookup
[CategoryID] [Category] [Subcategory]
100 Category1 Subcategory1
101 Category1 Subcategory2
102 Category1 Subcategory3
103 Category1 Subcategory4
200 Category2 SubcategoryA
201 Category2 SubcategoryB
202 Category2 SubcategoryC
etc.
Status lookup
[StatusID] [Description]
0 New
500 Accepted
501 Rejected
Status history
[key] [StatusID] [date]
AAAA 0 2017-01-01
BBBB 0 2017-01-01
CCCC 0 2017-01-01
DDDD 0 2017-01-01
EEEE 0 2017-01-01
FFFF 0 2017-01-01
GGGG 0 2017-01-01
AAAA 500 2017-01-02
BBBB 501 2017-01-02
EEEE 501 2017-01-02
FFFF 500 2017-01-02
BBBB 500 2017-01-03
EEEE 500 2017-01-03
etc.
I'd like to get a monthly summary of the results (which is emailed out). Right now I'm building the summary table in the code. I'd like to learn how to do it in SQL, but I don't really know where to start.
Final table where the totals are based on the last [Status History] value and ordered by [Total] DESC.
[Category] [Subcategory] [New] [Accepted] [Rejected] [Total]
Category1 Subcategory1 13 8 2 23
Category2 Subcategory3 10 4 6 20
Category1 Subcategory2 5 8 4 17
I've tried to look at PIVOT to do this, but I don't understand how to do it with the joins and with getting only the last status history value.
I think this is what you're after. I recreated your data and tested it out, but I definitely had to make one or two assumptions about the relationships involved. Try it and let me know:
select Category,
Subcategory,
sum(case when description = 'New' then 1 else 0 end) as New,
sum(case when description = 'Accepted' then 1 else 0 end) as Accepted,
sum(case when description = 'Rejected' then 1 else 0 end) as Rejected,
count(*) as Total
from
(select tB.Category, tB.Subcategory, status_lookup.Description
from status_history inner join (select my_key, max(status_date) as lastdate
from status_history
group by my_key) tA on status_history.my_key = tA.my_key
and status_history.status_date = tA.lastdate
inner join status_lookup on status_history.StatusID = status_lookup.StatusID
inner join (select main.my_key, category_lookup.Category, category_lookup.Subcategory
from main inner join category_lookup on main.CategoryID = category_lookup.CategoryID) tB on status_history.my_key = tB.my_key) tC
group by Category, Subcategory
I renamed your [key] column my_key, and called the tables main, category_lookup, status_lookup, and status_history respectively.
Related
Table A
ID name date_from date_to region manager
---------------------------------------------------------
1 Harry 2019-12-01 2020-01-01 south ABC
1 Harry 2020-01-01 2020-03-01 north BCD
1 Harry 2020-03-01 NULL East DCE
Table B
Date name H_time T_time
---------------------------------------
2019-12-01 Harry 30 20
2020-01-01 Harry 20 10
2020-02-01 Harry 40 50
2020-04-01 Harry 50 60
I wanted to check table B date falls into the date range above and return the specific region and manager info like...
Table C
Date name H_time T_time region manager
---------------------------------------------------------
2019-12-01 Harry 30 20 south ABC
2020-01-01 Harry 20 10 north BCD
2020-02-01 Harry 40 50 north BCD
2020-04-01 Harry 50 60 East DCE
You can use a join:
select b.*, a.region, a.manager
from b join
a
on b.name = a.name and
b.date >= a.date_from and
(b.date <= date_to or a.date_to is null);
Based on your expected result, this should do the trick
SELECT b.*, a.region, a.manager
FROM table_b b
INNER JOIN table_a a on b.name = a.name
WHERE
(b.date >= a.date_from and b.date < a.date_to)
OR
(b.date >= a.date_from and a.date_to IS NULL)
I'm trying to achieve sort of solution to the below table, as I need to make one of the rows in column as column
sku title name product_qty ID warehouse_id
-----------------------------------------------------
S001 Title 1 warehouse1 5 23 1
S001 Title 1 warehouse2 95 23 2
S001 Title 1 warehouse3 3 23 3
S002 Title 2 warehouse1 1 24 1
S002 Title 2 warehouse2 91 24 2
S002 Title 2 warehouse3 0 25 3
and what I would like to achieve
sku title name
warehouse 1 warehouse 2 warehouse 3
S001 Title 1 5 95 3
S002 Title 2 1 91 0
Please try this ... solution...You need to pivot the data.
CREATE TABLE Pivots
(
sku VARCHAR(10)
,title VARCHAR(10)
,name VARCHAR(10)
,product_qty INT
,ID INT
,warehouse_id INT
)
GO
INSERT INTO Pivots VALUES
('S001','Title1','warehouse1',5 , 23 , 1),
('S001','Title1','warehouse2',95 , 23 , 2),
('S001','Title1','warehouse3',3 , 23 , 3),
('S002','Title2','warehouse1',1 , 24 , 1),
('S002','Title2','warehouse2',91 , 24 , 2),
('S002','Title2','warehouse3',0 , 25 , 3)
GO
SOLUTION
SELECT sku,title titlename,ISNULL(MAX(x.warehouse1),0) warehouse1
,ISNULL(MAX(x.warehouse2),0) warehouse2 ,ISNULL(MAX(x.warehouse3),0) warehouse3 FROM Pivots p
PIVOT
(
MAX(product_qty) FOR name IN ([warehouse1],[warehouse2],[warehouse3])
)x
GROUP BY sku,title
OUTPUT
sku titlename warehouse1 warehouse2 warehouse3
---------- ---------- ----------- ----------- -----------
S001 Title1 5 95 3
S002 Title2 1 91 0
(2 rows affected)
SOLUTION 2 - USING conditional aggregation
SELECT sku,title titlename
,ISNULL(MAX(CASE WHEN name = 'warehouse1' THEN product_qty END),0) warehouse1
,ISNULL(MAX(CASE WHEN name = 'warehouse2' THEN product_qty END),0) warehouse2
,ISNULL(MAX(CASE WHEN name = 'warehouse3' THEN product_qty END),0) warehouse3
FROM Pivots p
GROUP BY sku,title
OUTPUT
sku titlename warehouse1 warehouse2 warehouse3
---------- ---------- ----------- ----------- -----------
S001 Title1 5 95 3
S002 Title2 1 91 0
(2 rows affected)
I have a list of customers that can have a single, or multiple, service listed. In the table that houses the changes over time there is an indicator of 'Added' or 'Removed'.
What I need: determine those service(s) that are currently active, if at all.
Here is a sample set of data:
CUST_ID SRV_ID STATUS ACTION_DATE
12345 102 Added 1/31/17 10:15
12345 189 Added 4/18/17 15:37
12345 189 Removed 4/21/17 14:08
12345 194 Added 5/2/17 14:43
12345 194 Removed 5/5/17 10:02
12345 194 Added 5/5/17 13:06
12345 69 Added 4/19/17 9:36
12345 69 Removed 5/2/17 14:43
12345 73 Added 4/20/17 10:21
12345 73 Removed 4/25/17 11:20
12345 95 Added 5/4/17 9:48
12345 95 Removed 5/4/17 10:05
Records to be returned: 102 on 1/31/17 10:15 and 194 on 5/5/17 13:06
You can find the latest row for each cust_id and serv_id using top 1 with ties and window function row_number and then filter those with status "Added":
select *
from (
select top 1
with ties *
from your_table
order by row_number() over (
partition by cust_id, srv_id
order by action_date desc
)
) t
where status = 'Added'
Produces:
CUST_ID SRV_ID STATUS ACTION_DATE
12345 102 Added 2017/01/31 10:15
12345 194 Added 2017/05/05 13:06
Demo
Like this:
SELECT SRV_ID
FROM YourTable
GROUP BY SRV_ID
HAVING MAX(CASE WHEN STATUS='Added' THEN ACTION_DATE END)
> MAX(CASE WHEN STATUS='Removed' THEN ACTION_DATE END)
I am trying to retrieve the most recent entry of a record in an Access report. The query I have gives me the results in SQL-Server but row_number is not compatible with Access. Its been suggested that I use the max function in Access. Can you assist me in generating this report?
SELECT cID, CName, Address, Project#, JobOwner, SubStatusID, Status, JNJobID, JNNote
FROM (
SELECT
cID, CName, Address, Project#, JobOwner, SubStatusID, Status, JNJobID, JNNote
, ROW_NUMBER() OVER (PARTITION BY JNJobID ORDER BY JNDate DESC) AS r
FROM [JobNotes]
Left JOIN Jobs ON [JobNotes].JNJobID = Jobs.JobID
Left JOIN Addresses ON Jobs.JobAddressID = Addresses.AddressID
Left JOIN Customers ON Jobs.JobCustomerID = Customers.CID
Left JOIN Status ON Jobs.JobSubStatusID = Status.StatusID
) x
WHERE r = 1 and customerID = 134 and jobsubstatusid <> 14 and jobsubstatusid <> 15 and jobsubstatusid <> 16 and jobsubstatusid <> 42 and jobsubstatusid <>38 and jobsubstatusid <>75
Jobs Table
JobID Project# JobOwner JobStatusID AddressID JobCustomerID
6972 PN1 John 1 333 222
6973 PN2 Sarah 3 444 666
6974 PN3 James 6 555 777
Address Table
AddressID Address
333 1333 Janes Ln
444 5555 Davis Blvd
555 888 Post Rd
Customer Table
CID CName
222 Builder
666 HomeOwner
777 HOA
JobNotes Table
JobNotesID JNJobID JNDate JNNote
11800 6972 2016-03-15 00:00:00.000 Example 1
11874 6972 2016-03-17 00:00:00.000 Example 2
12181 6972 2016-03-25 00:00:00.000 Example 3
12006 6973 2016-03-21 00:00:00.000 Example 4
11961 6974 2016-03-18 00:00:00.000 Example 5
11924 6974 2016-03-17 00:00:00.000 Example 6
JobNotes Table
CID CName Address Project# JobOwner SubStatusID Status JNJobID JNNote
222 Builder 1333 Janes Ln PN1 John 1 Sales 6972 Example 3
666 HomeOwner 5555 Davis Blvd PN2 Sarah 3 Design 6973 Example 4
777 HOA 888 Post Rd PN3 James 6 Construction 6974 Example 6
I have data looks like this:
Order No. Name Date Unit Price Freight
001 ABC 1-16 232 25
001 ABC 1-16 55 25
001 ABC 1-16 156 25
002 DEF 2-5 478 16
002 DEF 2-5 356 16
I am trying to let freight cost only show once in my table, the result would look like:
Order No. Name Date Unit Price Freight
001 ABC 1-16 232 25
001 ABC 1-16 55 0
001 ABC 1-16 156 0
002 DEF 2-5 478 16
002 DEF 2-5 356 0
Please help me with this
Here is a query to get what you want:
SELECT
order_no, name, theDate, unit_price,
case
when row_number() OVER (PARTITION by order_no ORDER BY order_no) = 1 then freight
else 0
end as freight
from yourTable
This looks at all rows for each order number and provides the row number. If it's row 1 of that order it uses the values of the freight column, otherwise it uses 0.
Note that I'm assuming that the freight value is the same across all rows for the same order number.