I have the following data:
-----------------
Name|Value|Type
-----------------
A | 110 | Daily
-----------------
A | 770 | Weekly
-----------------
B | 150 | Daily
-----------------
B | 700 | Weekly
-----------------
C | 120 | Daily
-----------------
C | 840 | Weekly
In SSRS bar chart, the Name will be X axis, the Value will be Y axis, the Type will be series.
What I need is the bar chart will sort by the Weekly Value descending, so the expected order should be:
C Weekly
C Daily
A Weekly
A Daily
B Weekly
B Daily
How to do that? In query or in SSRS chart setting?
You can use ROW_NUMBER() to generate sequential number for each Name based on the Value for Weekly type and which will then be the basis on how the records will be sorted.
WITH records
AS
(
SELECT Name,
ROW_NUMBER() OVER (ORDER BY Value DESC) rn
FROM tableName
WHERE Type = 'Weekly'
)
SELECT a.*
FROM tableName a
INNER JOIN records b
ON a.Name = b.Name
ORDER BY b.rn, a.Type DESC
SQLFiddle Demo
OUTPUT
╔══════╦═══════╦════════╗
║ NAME ║ VALUE ║ TYPE ║
╠══════╬═══════╬════════╣
║ C ║ 840 ║ Weekly ║
║ C ║ 120 ║ Daily ║
║ A ║ 770 ║ Weekly ║
║ A ║ 110 ║ Daily ║
║ B ║ 700 ║ Weekly ║
║ B ║ 150 ║ Daily ║
╚══════╩═══════╩════════╝
Related
I have the following table, it displays the SalesQty and the StockQty grouped by Article, Supplier, Branch and Month.
╔════════╦════════╦══════════╦═════════╦══════════╦══════════╗
║ Month ║ Branch ║ Supplier ║ Article ║ SalesQty ║ StockQty ║
╠════════╬════════╬══════════╬═════════╬══════════╬══════════╣
║ 201811 ║ 333 ║ 2 ║ 3122 ║ 4 ║ 11 ║
║ 201811 ║ 345 ║ 1 ║ 1234 ║ 2 ║ 10 ║
║ 201811 ║ 345 ║ 1 ║ 4321 ║ 3 ║ 11 ║
║ 201812 ║ 333 ║ 2 ║ 3122 ║ 2 ║ 4 ║
║ 201812 ║ 345 ║ 1 ║ 1234 ║ 3 ║ 12 ║
║ 201812 ║ 345 ║ 1 ║ 4321 ║ 4 ║ 5 ║
║ 201901 ║ 333 ║ 2 ║ 3122 ║ 1 ║ 8 ║
║ 201901 ║ 345 ║ 1 ║ 1234 ║ 6 ║ 9 ║
║ 201901 ║ 345 ║ 1 ║ 4321 ║ 2 ║ 8 ║
║ 201902 ║ 333 ║ 2 ║ 3122 ║ 7 ║ NULL ║
║ 201902 ║ 345 ║ 1 ║ 1234 ║ 4 ║ 13 ║
║ 201902 ║ 345 ║ 1 ║ 4321 ║ 1 ║ 10 ║
╚════════╩════════╩══════════╩═════════╩══════════╩══════════╝
Now I want to sum the SalesQty and get the latest StockQty and group them by Article, Supplier, Branch.
The final result should look like this:
╔════════╦══════════╦═════════╦═════════════╦════════════════╗
║ Branch ║ Supplier ║ Article ║ SumSalesQty ║ LatestStockQty ║
╠════════╬══════════╬═════════╬═════════════╬════════════════╣
║ 333 ║ 2 ║ 3122 ║ 14 ║ NULL ║
║ 345 ║ 1 ║ 1234 ║ 15 ║ 13 ║
║ 345 ║ 1 ║ 4321 ║ 10 ║ 10 ║
╚════════╩══════════╩═════════╩═════════════╩════════════════╝
I already tried this but it gives me an error, and i have no idea what i have to do in this case.
I've made this example so you can try it by yourself. db<>fiddle
SELECT
Branch,
Supplier,
Article,
SumSalesQty = SUM(SalesQty),
-- my attempt
LatestStockQty = (SELECT StockQty FROM TestTable i
WHERE MAX(Month) = Month
AND TT.Branch = i. Branch
AND TT.Supplier = i.Branch
AND TT.Article = i.Branch)
FROM
TestTable TT
GROUP BY
Branch, Supplier, Article
Thank you for your help!
We can try using ROW_NUMBER here, to isolate the latest record for each group:
WITH cte AS (
SELECT t.*, ROW_NUMBER() OVER (PARTITION BY Branch, Supplier, Article
ORDER BY Month DESC) rn,
SUM(SalesQty) OVER (PARTITION BY Branch, Supplier, Article) SumSalesQty
FROM TestTable t
)
SELECT
Month,
Branch,
Supplier,
Article,
SumSalesQty,
StockQty
FROM cte
WHERE rn = 1;
Inside the CTE we compute, for each Branch/Supplier/Article group a row number value, starting with 1 for the most recent month. We also compute the sum of the sales quantity over the same partition. Then, we only need to select all rows from that CTE where the row number is equal to 1.
Demo
A similar approach but without the CTE
SELECT top 1 with ties
Branch
, Supplier
, Article
, SUM(SalesQty) OVER (PARTITION BY Branch, Supplier, Article) SumSalesQty
, tt.StockQty as LatestStockQty
FROM TestTable TT
order by ROW_NUMBER() OVER (PARTITION BY Branch, Supplier, Article ORDER BY Month DESC)
I have a table with records like history table.
I have created following Query to get the desired result. However, it is not giving me final result that I want.
DECLARE #Customer_Id BIGINT=4
DECLARE #Month INT=2
SELECT
FH.UniqueFileId,FH.DocumentNo,MIN(FH.DateStamp) AS ReceivedTime,MAX(FH.DateStamp) SentTime
FROM
[dbo].[FileMovement_History] FH
INNER JOIN [dbo].[User_Master] UM ON UM.User_Id=FH.User_Id
WHERE
FH.UniqueFileId Is Not NULL AND FH.UniqueFileId!=''
AND (#Customer_Id IS NULL OR UM.Customer_id = #Customer_Id)
AND MONTH(FH.DateStamp)=#Month
GROUP BY
FH.UniqueFileId,FH.DocumentNo
Order BY
FH.UniqueFileId
╔════════════════╦══════════════════════╦═════════════════════════════╦═════════════════════════════╗
║ UniqueFileId ║ DocumentNo ║ ReceivedTime ║ SentTime ║
╠════════════════╬══════════════════════╬═════════════════════════════╬═════════════════════════════╣
║ HS5536387_10HE ║ NULL ║ 2017-02-02 13:13:37.3451906 ║ 2017-02-02 13:19:19.0114047 ║
║ HS5536387_10HE ║ 120097583 / MC / CL7 ║ 2017-02-02 13:19:18.9801503 ║ 2017-02-02 13:19:19.1051605 ║
║ HS5536387_1HE ║ NULL ║ 2017-02-02 13:13:34.6887572 ║ 2017-02-02 13:21:37.7405652 ║
║ HS5536387_1HE ║ 3701341 ║ 2017-02-02 13:21:37.6936641 ║ 2017-02-02 13:21:37.8499434 ║
║ HS5536387_3HE ║ NULL ║ 2017-02-02 13:13:35.5950873 ║ 2017-02-02 13:19:19.9958519 ║
╚════════════════╩══════════════════════╩═════════════════════════════╩═════════════════════════════╝
I want the following result where I need one entry for one UniqueFileId with minimum of datestamp and maximum of datestamp. I want extra column where is shows total timeduration between minimum and maximum date.
╔════════════════╦══════════════════════╦═════════════════════════════╦═════════════════════════════╗
║ UniqueFileId ║ DocumentNo ║ ReceivedTime ║ SentTime ║
╠════════════════╬══════════════════════╬═════════════════════════════╬═════════════════════════════╣
║ HS5536387_10HE ║ 120097583 / MC / CL7 ║ 2017-02-02 13:13:37.3451906 ║ 2017-02-02 13:19:19.0114047 ║
║ HS5536387_1HE ║ 3701341 ║ 2017-02-02 13:13:34.6887572 ║ 2017-02-02 13:21:37.7405652 ║
║ HS5536387_3HE ║ NULL ║ 2017-02-02 13:13:35.5950873 ║ 2017-02-02 13:19:19.9958519 ║
╚════════════════╩══════════════════════╩═════════════════════════════╩═════════════════════════════╝
Do a grouping only by the UniqueFileId field, and instead take the MIN(DocumentNo) value of this column:
SELECT FH.UniqueFileId,
MIN(FH.DocumentNo) AS DocumentNo,
MIN(FH.DateStamp) AS ReceivedTime,
MAX(FH.DateStamp) AS SentTime
FROM [dbo].[FileMovement_History] FH
INNER JOIN [dbo].[User_Master] UM
ON UM.User_Id = FH.User_Id
WHERE COALESCE(FH.UniqueFileId, '') <> '' AND
(#Customer_Id IS NULL OR UM.Customer_id = #Customer_Id) AND
MONTH(FH.DateStamp) = #Month
GROUP BY FH.UniqueFileId
ORDER BY FH.UniqueFileId
If you want to show the difference in time between the sent and received time in the format hh:mm:ss, then you can use the following expression:
CAST(DATEDIFF(HOUR, MIN(FH.DocumentNo), MAX(FH.DocumentNo)) AS NVARCHAR(200)) + ":" +
CAST(DATEDIFF(MINUTE, MIN(FH.DocumentNo), MAX(FH.DocumentNo)) % 60 AS NVARCHAR(200)) +":" +
CAST(DATEDIFF(SECOND, MIN(FH.DocumentNo), MAX(FH.DocumentNo)) % 60 AS NVARCHAR(200))
I have stumbled upon an interesting challenge. I have data in a SQL Server table with the following format/content.
Date | Name
---------+---------
1/1/2010 | John
1/1/2010 | Mark
1/1/2010 | Peter
1/1/2010 | Mia
2/4/2010 | John
2/4/2010 | Billy
I am trying to convert that table into a file containing edges of a graph.
I'll need the edges file to have to columns and all the combinations that the table shows.
John | Mark
John | Peter
John | Mia
Mark | Mia
Mark | Peter
Peter | Mia
John | Billy
I suspect part of this can be achieved with pivot/unpivot but don't know how to proceed with limiting the pivot to only two columns.
Also, I don't know how to make sure I get all the possible combinations of nodes, see that the first four 'nodes' need to become six 'edges.'
You could use ROW_NUMBER and "triangle join":
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY Name)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
LiveDemo
Output:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Mia ║
║ John ║ Peter ║
║ Mark ║ Mia ║
║ Mark ║ Peter ║
║ Mia ║ Peter ║ -- ORDER BY based on `Name`
║ Billy ║ John ║ -- same here `B` before `J`
╚═══════╩═══════╝
Note:
To get stable sort you need to add column that will indicate order within group with the same date. I used Name but it swaps the names in last two rows.
Version with ID column:
CREATE TABLE tab(ID INT IDENTITY(1,1)
,Date DATE NOT NULL
,Name VARCHAR(6) NOT NULL);
INSERT INTO tab(Date,Name)
VALUES ('1/1/2010','John'), ('1/1/2010','Mark'), ('1/1/2010','Peter')
,('1/1/2010','Mia'), ('2/4/2010','John'),('2/4/2010','Billy');
WITH cte AS
(
SELECT *, rn = ROW_NUMBER() OVER(PARTITION BY date ORDER BY ID)
FROM tab
)
SELECT c.Name, c2.Name
FROM cte c
JOIN cte c2
ON c.Date = c2.Date
AND c.rn < c2.rn;
LiveDemo 2
Output:
╔═══════╦═══════╗
║ Name ║ Name ║
╠═══════╬═══════╣
║ John ║ Mark ║
║ John ║ Peter ║
║ John ║ Mia ║
║ Mark ║ Peter ║
║ Mark ║ Mia ║
║ Peter ║ Mia ║
║ John ║ Billy ║
╚═══════╩═══════╝
Table T:
ID | Name | Days
ID is the PK.
I do want to select * from T, order by ID descending, but on TOP to be those entries which have the ID between 1000 and 1004
select *
from T
order by Id descending // something like a *case*?
1004 - 1st / 1003 2nd / 1002 3rd / 1001 4th / 1000 5nd ... and then 6th should be the max Id, and after this all descending excepting the Ids between 1000 - 1004 which we already displayed on the TOP.
I would like to know also the linq statement.
SELECT *
FROM (VALUES (998), (999), (1000), (1001), (1002), (1003), (1004)) AS T(ID)
ORDER BY CASE
WHEN T.ID BETWEEN 1000 AND 1004 THEN 1
ELSE 2
END
, ID DESC;
Took sample data from Sick's answer.
How does this work?
It checks whether your ID is matching your criteria and assign it a
value of 1
Everything else will have 2
It will sort by this value first
Your IDs with matching criteria will ALWAYS come first
Then we sort leftovers by ID in DESC order
Output:
╔══════╗
║ ID ║
╠══════╣
║ 1004 ║
║ 1003 ║
║ 1002 ║
║ 1001 ║
║ 1000 ║
║ 999 ║
║ 998 ║
╚══════╝
I've made additional example, which generates 676.800 rows in our DB:
;WITH TestTable (ID)
AS (
SELECT ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM sys.objects
CROSS JOIN sys.schemas
)
SELECT *
FROM TestTable AS T
ORDER BY CASE
WHEN T.ID BETWEEN 1000 AND 1004 THEN 1
ELSE 2
END
, ID DESC;
That's its result:
╔════════╗
║ ID ║
╠════════╣
║ 1004 ║
║ 1003 ║
║ 1002 ║
║ 1001 ║
║ 1000 ║
║ 676800 ║
║ 676799 ║
║ 676798 ║
║ 676797 ║
║ 676796 ║
║ 676795 ║
║ ... ║
║ 1006 ║
║ 1005 ║
║ 999 ║
║ 998 ║
║ ... ║
║ 1 ║
╚════════╝
Try this
select *
from T
order by case when ID between 1000 and 1004 then -100000 else id end,ID desc
Here -100000 is s random low value
Example :
SELECT *
FROM (VALUES (998),
(999),
(1000),
(1001),
(1002),
(1003),
(1004) ) tc (id)
ORDER BY CASE
WHEN ID BETWEEN 1000 AND 1004 THEN -100000
ELSE id
END,
ID DESC
SELECT column_name, column_name
FROM table_name
ORDER BY column_name ASC|DESC, column_name ASC|DESC;
I am sorry for the kind of ambiguous title up there but I don't think there is an easy way to explain what I am trying to do here.
I have the table below in my SQL database:
╔═══════╦══════════════════════════╦════════════╦════════════════╦════════════════╦════════════════╗
║ ID ║ Short Name ║ Day ║ CSFB ║ SomeNumberHere ║ DCR ║
║ 58144 ║ PERSVN_L26_C_1 ║ 06/10/2014 ║ 588 ║ 588 ║ 15727 ║
║ 58145 ║ PERSVN_L26_C_1 ║ 07/10/2014 ║ 587 ║ 587 ║ 16733 ║
║ 58146 ║ PERSVN_L18_C_1 ║ 08/10/2014 ║ 640 ║ 640 ║ 15109 ║
║ 58250 ║ PETERLORANGESVEI_L18_C_1 ║ 12/10/2014 ║ 53 ║ 53 ║ 2765 ║
║ 58251 ║ PHILIPPEDERSEN_L08_A2_1 ║ 03/10/2014 ║ 24 ║ 24 ║ 1003 ║
╚═══════╩══════════════════════════╩════════════╩════════════════╩════════════════╩════════
I want to create an extra row in this table, which will be calculated by adding the DCR + CSFB row numbers IF the short name contains L26, DCR - CSFB IF the short name contains L18 and DCR / CSFB IF the short name contains L08.
The result, would look like this:
╔═══════╦══════════════════════════╦═════════════╦════════════╦═══════╦════════════════╦═══════╗
║ ID ║ Short Name ║ Calculation ║ Day ║ CSFB ║ SomeNumberHere ║ DCR ║
║ 58144 ║ PERSVN_L26_C_1 ║ {CSFB+DCR} ║ 06/10/2014 ║ 588 ║ 588 ║ 15727 ║
║ 58145 ║ PERSVN_L26_C_1 ║ {CSFB+DCR} ║ 07/10/2014 ║ 587 ║ 587 ║ 16733 ║
║ 58146 ║ PERSVN_L18_C_1 ║ {CSFB-DCR} ║ 08/10/2014 ║ 640 ║ 640 ║ 15109 ║
║ 58250 ║ PETERLORANGESVEI_L18_C_1 ║ {CSFB-DCR} ║ 12/10/2014 ║ 53 ║ 53 ║ 2765 ║
║ 58251 ║ PHILIPPEDERSEN_L08_A2_1 ║ {CSFB/DCR} ║ 03/10/2014 ║ 24 ║ 24 ║ 1003 ║
╚═══════╩══════════════════════════╩═════════════╩════════════╩═══════╩════════════════╩═══════╝
Can you help me go about it?
One way is to create three different tmp tables with a "where [Short Name] like '%Lxx%'"
and then merge them together, but I am trying to avoid that. A stored procedure would do you think ? Thanks for the help
If I understand you correct you want the calculation performed per row? If so this query should be what you want. If you need it in the table permanently you can use the case expression as source for a computed column.
SQL Fiddle
MS SQL Server 2008 Schema Setup:
CREATE TABLE Table1
([ID] int, [Short Name] varchar(24), [Day] datetime, [CSFB] int, [SomeNumberHere] int, [DCR] int)
;
INSERT INTO Table1
([ID], [Short Name], [Day], [CSFB], [SomeNumberHere], [DCR])
VALUES
(58144, 'PERSVN_L26_C_1', '2014-06-10 02:00:00', 588, 588, 15727),
(58145, 'PERSVN_L26_C_1', '2014-07-10 02:00:00', 587, 587, 16733),
(58146, 'PERSVN_L18_C_1', '2014-08-10 02:00:00', 640, 640, 15109),
(58250, 'PETERLORANGESVEI_L18_C_1', '2014-12-10 01:00:00', 53, 53, 2765),
(58251, 'PHILIPPEDERSEN_L08_A2_1', '2014-03-10 01:00:00', 24, 24, 1003)
;
Query 1:
SELECT
ID,
[Short Name],
CASE
WHEN [Short Name] LIKE '%L26%' THEN DCR+CSFB
WHEN [Short Name] LIKE '%L18%' THEN DCR-CSFB
WHEN [Short Name] LIKE '%L08%' THEN DCR/CSFB
END AS Calculation,
Day,
CSFB,
SomeNumberHere,
DCR
FROM TABLE1
Results:
| ID | SHORT NAME | CALCULATION | DAY | CSFB | SOMENUMBERHERE | DCR |
|-------|--------------------------|-------------|---------------------------------|------|----------------|-------|
| 58144 | PERSVN_L26_C_1 | 16315 | June, 10 2014 02:00:00+0000 | 588 | 588 | 15727 |
| 58145 | PERSVN_L26_C_1 | 17320 | July, 10 2014 02:00:00+0000 | 587 | 587 | 16733 |
| 58146 | PERSVN_L18_C_1 | 14469 | August, 10 2014 02:00:00+0000 | 640 | 640 | 15109 |
| 58250 | PETERLORANGESVEI_L18_C_1 | 2712 | December, 10 2014 01:00:00+0000 | 53 | 53 | 2765 |
| 58251 | PHILIPPEDERSEN_L08_A2_1 | 41 | March, 10 2014 01:00:00+0000 | 24 | 24 | 1003 |
Just Add a computed column to the table, with the computed value being based on a CASE statement.
ie:
ALTER tableName
ADD [Calculation] DECIMAL(14,5) AS CASE WHEN [Short Name] LIKE '%L26%' THEN DCR + CSFB
WHEN [Short Name] LIKE '%L18%' THEN DCR - CSFB
WHEN [Short Name] LIKE '%L08%' THEN DCR / CSFB
ELSE 0 END