TSQL - Select Latest Date by 2 Type - sql

I need select data in SQL Server.
I have a Data example like this
DECLARE #tblA TABLE (ID int, SubId int, Createdate DateTime)
INSERT INTO #tblA VALUES (1, 1, '10/21/2020')
, (2, 1, '10/21/2020')
, (3, 1, '10/27/2020')
, (4, 2, '10/21/2020')
, (5, 2, '10/21/2020')
, (6, 1, '10/21/2020')
, (7, 2, '10/23/2020')
, (8, 2, '10/22/2020')
, (9, 1, '10/25/2020')
, (10, 3, '10/21/2020')
I want to get 4 records (in table will have a lot of SubId)
2 records latest date by SubId = 1
2 records latest date by SubId = 2
Following example, I expect Select with like table Output
DECLARE #tblOutput Table (ID int, SubId int, Createdate DateTime)
INSERT INTO #tblOutput VALUES (3, 1, '10/27/2020')
, (9, 1, '10/25/2020')
, (7, 2, '10/23/2020')
, (8, 2, '10/22/2020')
"tooltip"
I try with Union but It's only Order after Union. It's not the result I want.
Please, Help me to select this.
Thank you.

You can use the Row_Number() function as shown below:
Create table tblA (ID int, SubId int, Createdate DateTime)
Insert Into tblA values (1, 1, '10/21/2020')
, (2, 1, '10/21/2020')
, (3, 1, '10/27/2020')
, (4, 2, '10/21/2020')
, (5, 2, '10/21/2020')
, (6, 1, '10/21/2020')
, (7, 2, '10/23/2020')
, (8, 2, '10/22/2020')
, (9, 1, '10/25/2020')
, (10, 3, '10/21/2020')
select Id
, SubId
, Createdate
from(
select *
, Row_Number() Over (Partition By SubId order by Createdate desc) as RNo
from tblA
)temp where RNo <= 2 and SubId in (1, 2)
Order by SubId
Live db<>fiddle demo

Related

How to write a SQL statement to return all children of each root,extend to each root

I have a table.
the value of [contents] can insert any word(Below are just examples)
create table #TreeTable (
Id uniqueidentifier,
Contents NVARCHAR(200),
ParentId uniqueidentifier,
Floors Int,
Sort Int,
)
insert into #TreeTable([Id], [ParentId], [Contents],[Floors],[Sort]) values
(1, 0, '1',1,1),
(2, 0, '2',1,2),
(3, 1, '1-1',2,1),
(4, 1, '1-2',2,2),
(5, 2, '2-1',2,1),
(6, 3, '1-1-1',3,1),
(7, 4, '1-2-1',3,1);
(8, 4, '1-2-2',3,2),
(9, 6, '1-1-1-1',4,1),
(10, 6,'1-1-1-2',4,2);
I want to write a T-SQL statement that will return all children of each root with the root ID and Below is the result I expected
[Id][ParentId][Contents] [Levels][Sort]
(1, 0, '1', 1, 1)
(3, 1, '1-1', 2, 1)
(6, 3, '1-1-1', 3, 1)
(9, 6, '1-1-1-1', 4, 1)
(10, 6, '1-1-1-2', 4, 2)
(4, 1, '1-2', 2, 2)
(7, 4, '1-2-1', 3, 1)
(8, 4, '1-2-2', 3, 2)
(2, 0, '2', 1, 2)
(5, 2, '2-1', 2, 1)
The depth of the tree may be arbitrarily long
I try to use this ,but the reuslt is not what i expected
with RecursiveTable as(
------ start-------
SELECT a.*
FROM TreeTable a
WHERE
a.ParentId = 0
------ end ---------
union all
SELECT b.*
FROM TreeTable b
join RecursiveTable a on a.Id =b.ParentId
)
select * from RecursiveTable
If we may believe [Contents] values, then simply
SELECT [Id],
[ParentId],
[Contents],
LEN([Contents]) - LEN(REPLACE([Contents], '-', '')) + 1 [Levels],
[Sort]
FROM #TreeTable
ORDER BY [Contents];
fiddle
If not then
WITH cte AS
(
SELECT [Id], [ParentId], CAST([Sort] AS NCHAR), [Sort], 1 [Levels]
FROM #TreeTable
WHERE [ParentId] = 0
UNION ALL
SELECT t.[Id], t.[ParentId], cte.[Contents] + '-' + t.[Sort], t.[Sort], 1 + cte.[Levels]
FROM #TreeTable t
JOIN cte ON t.[ParentId] = cte.[Id]
)
SELECT [Id], [ParentId], [Contents], [Levels], [Sort]
FROM cte
ORDER BY [Contents];
fiddle (optimize types adjusting for their matching in CTE by yourself).
U can try:
WITH RECURSIVETABLE (ID, [PARENTID], [CONTENTS],[LEVELS],[SORT],[ORDER]) AS
(
------ START-------
SELECT A.ID, A.[PARENTID], A.[CONTENTS],A.[FLOORS],A.[SORT], CONVERT(VARCHAR(250),RIGHT('00000'+CONVERT(VARCHAR(50),ROW_NUMBER() OVER(ORDER BY SORT)),5))
FROM #TREETABLE A
WHERE
A.PARENTID = 0
------ END ---------
UNION ALL
SELECT B.ID, B.[PARENTID], B.[CONTENTS],B.[FLOORS],B.[SORT], CONVERT(VARCHAR(250),CONVERT(VARCHAR,A.[ORDER])+'.'+RIGHT('00000'+CONVERT(VARCHAR(50),ROW_NUMBER() OVER(ORDER BY B.[FLOORS],B.SORT)),5))
FROM #TREETABLE B
JOIN RECURSIVETABLE A ON A.ID =B.PARENTID
)
SELECT * FROM RECURSIVETABLE ORDER BY [ORDER]

Joining two different tables with a common third table on a common column

Here are the tables
Table: Status
ID, StatusDesc
1, New
2, Active
3, Cancelled
4, Complete
Table: Order (foreign key relationship with Status table above)
ID, OrderNumber, StatusID
1, 1001 , 1
2, 1002, 1
3, 1003, 2
4, 1004, 3
5, 1500, 4
Table: LineItem(foreign key relationship with Order and Status tables above)
ID, OrderNumber, LineItemNumber, StatusID
1, 1001 , 1, 1
2, 1001 , 2, 1
3, 1002 , 1, 2
4, 1002 , 2, 1
5, 1003 , 1, 2
6, 1004 , 1, 3
7, 1004 , 2, 4
8, 1500 , 1, 3
As you can see, the table Status holds the statuses common for both Order and LineItem tables.
I want to produce the result which will include columns like this, status description for both Order and LineItem:
OrderNumber, LineItemNumber, StatusDesc_Order, StatusDesc_LineItem
How to do this?
You could join the Status table twice to achieve this:
SELECT
o.OrderNumber
, li.LineItemNumber
, orderStatus.StatusDesc AS StatusDesc_Order
, lineItemStatus.StatusDesc AS StatusDesc_LineItem
FROM [LineItem] AS li
INNER JOIN [Status] AS lineItemStatus ON li.StatusID = lineItemStatus.ID
INNER JOIN [Order] AS o ON li.OrderNumber = o.OrderNumber
INNER JOIN [Status] AS orderStatus ON o.StatusID = orderStatus.ID
I do suggest however you try and stay away from table names using reserved keywords like Order and Status, it also is good practice to explcitly add schema prefixes before the table names in the query (i.e. dbo.Status or another user defined schema).
If the required results really are that simple then just use a couple of sub-queries e.g.
-- SETUP TEST DATA
declare #Order table (id int, OrderNumber int, StatusId int)
insert into #Order (id, OrderNumber, StatusId)
values (1, 1001, 1), (2, 1002, 1), (3, 1003, 2), (4, 1004, 3), (5, 1500, 4)
declare #LineItem table (id int, OrderNumber int, LineItemNumber int, StatusId int)
insert into #LineItem (id, OrderNumber, LineItemNumber, StatusId)
values (1, 1001, 1, 1), (2, 1001, 2, 1), (3, 1002, 1, 2), (4, 1002, 2, 1), (5, 1003, 1, 2), (6, 1004, 1, 3), (7, 1004, 2, 4), (8, 1500, 2, 3)
declare #Status table (id int, StatusDesc varchar(32))
insert into #Status(id, StatusDesc)
values (1,'New'), (2,'Active'), (3,'Cancelled'), (4,'Complete')
-- QUERY DATA
select LI.OrderNumber, LI.LineItemNumber
, (select S.StatusDesc from #Status S where S.id = StatusId) [StatusDesc_Order]
, (select S.StatusDesc from #Status S where S.id = (select O.StatusId from #Order O where O.OrderNumber = LI.OrderNumber)) [StatusDesc_LineItem]
from #LineItem LI
order by LI.OrderNumber, LI.LineItemNumber
Note: If you provide your sample data in this format in future questions you make your question much easier to answer.

SQL select distinct data without ordering the column

I have table which contains data as below:
DECLARE #CheckList TABLE
(
RowNumber INT IDENTITY(1,1) INT,
CheckId INT,
Treat INT
)
INSERT INTO #CheckList
VALUES (1, 1, 1), (1, 3, 1), (1, 2, 1), (1, 1, 1),
(1, 3, 1), (1, 2, 1), (1, 1, 3), (1, 3, 3),
(1, 2, 3);
SELECT DISTINCT Id, CheckId
FROM #CheckList
WHERE Id = 1
Where I want to select the data from this table as
Id CheckId
------------
1 1
1 3
1 2
I want the same order of the check id which is available in table. Can you help me with this?
Retain original ordering by RowNumber identity column
select Id,CheckId
from(
select distinct Id,CheckId, min(rownumber) over(partition by Id,CheckId) rn
from #CheckList
where Id=1
) t
order by rn;
Db fiddle
you can check this
DECLARE #CheckList TABLE
( Id INT , CheckId INT, Treat INT )
INSERT INTO #CheckList
VALUES (1, 1, 1), (1, 3, 1), (1, 2, 1), (1, 1, 1),(1, 3, 1), (1, 2, 1), (1, 1, 3),(1,3,3), (1, 2, 3);
SELECT DISTINCT Id, CheckId
FROM #CheckList
WHERE Id = 1

MINIMUM on second column, take first and third

DECLARE #Foo TABLE (Id INT, PozId INT, Val INT)
INSERT #Foo (Id, PozId, Val)
VALUES
(1, 1, 34),
(1, 2, 976),
(2, 1, 235),
(2, 2, 792),
(3, 2, 456),
(3, 3, 123)
How to get results like this from above query?
(1, 1, 34)
(2, 1, 235)
(3, 2, 456)
This brings you desired result. Query partitions your Ids and picks lowest PozitionId.
DECLARE #Foo TABLE
(
Id INT, PozId INT, Val INT
);
INSERT #Foo
(Id, PozId, Val)
VALUES
(1, 1, 34)
, (1, 2, 976)
, (2, 1, 235)
, (2, 2, 792)
, (3, 2, 456)
, (3, 3, 123);
SELECT Id, PozId, Val
FROM (
SELECT ROW_NUMBER() OVER (PARTITION BY Id ORDER BY PozId) AS RowNo, *
FROM #Foo
) AS T
WHERE RowNo = 1;

Concatenating in one column based on another column

I'm working with SQL Server 2008.
Let's say I have these three tables:
Product
1, "Honda Civic"
2, "Fiat Ritmo"
3, "Ford Fiesta"
ProductGroup
1, 1, 1
2, 1, 2
3, 3, 1
4, 2, 3
5, 2, 4
6, 1, 5
Group
1 American
2 Asian
3 European
4 Old
5 Fast
And let's say I want to query these tables so as to get the following:
"Fiat Ritmo", "European, Old"
"Honda Civic", "Asian, Fast"
"Ford Focus", "American"
How can I do this?
I'm using paging on the client side so I can't group the pages there.
Thanks for your help,
Barry
Something like this:
First some test data:
DECLARE #Product TABLE(ID INT, Name VARCHAR(100))
INSERT INTO #Product
SELECT 1,'Honda Civic' UNION ALL
SELECT 2,'Fiat Ritmo' UNION ALL
SELECT 3,'Ford Fiesta'
DECLARE #ProductGroup TABLE(ID INT,ProductID INT, GroupID INT)
INSERT INTO #ProductGroup
SELECT 1, 1, 1 UNION ALL
SELECT 2, 1, 2 UNION ALL
SELECT 3, 3, 1 UNION ALL
SELECT 4, 2, 3 UNION ALL
SELECT 5, 2, 4 UNION ALL
SELECT 6, 1, 5
DECLARE #Group TABLE(ID INT, Name VARCHAR(100))
INSERT INTO #Group
SELECT 1, 'American' UNION ALL
SELECT 2, 'Asian' UNION ALL
SELECT 3, 'European' UNION ALL
SELECT 4, 'Old' UNION ALL
SELECT 5, 'Fast'
Then the query:
SELECT
Product.ID,
Product.Name,
STUFF
(
(
SELECT
',' + Groups.Name
FROM
#ProductGroup AS ProductGroup
JOIN #Group AS Groups
ON ProductGroup.GroupID=Groups.ID
WHERE
ProductGroup.ProductID = Product.ID
FOR XML PATH('')
),1,1,'') AS Names
FROM
#Product AS Product
Use FOR XML PATH feature to get string grouping like this:
DECLARE #Product TABLE (Id INT PRIMARY KEY, Name NVARCHAR(100) NOT NULL)
INSERT #Product
VALUES(1, 'Honda Civic'), (2, 'Fiat Ritmo'), (3, 'Ford Fiesta')
DECLARE #ProductGroup TABLE(Product INT, Grp INT, PRIMARY KEY(Product, Grp))
INSERT #ProductGroup
VALUES
(1, 1),
(1, 2),
(3, 1),
(2, 3),
(2, 4),
(1, 5)
DECLARE #Grp TABLE(Id INT PRIMARY KEY, NAME NVARCHAR(100))
INSERT #Grp
VALUES
(1, 'American'),
(2, 'Asian'),
(3, 'European'),
(4, 'Old'),
(5, 'Fast')
SELECT p.name,
(
SELECT Name+','
FROM #ProductGroup pg
JOIN #Grp g
ON pg.Grp = g.Id
WHERE pg.Product = p.Id
FOR XML PATH('')
) Groups
FROM #Product p