SQL query cast from a group - sql

I'm trying to make a query whit a 'cast group by' - output.
But not quit sure how to tackle this or even to start (I think i need cast and group by but not sure).
I have some code below which hopefully explains what I'm trying to do.
Could somebody help me to make a query to have the correct output?
CREATE TABLE buyers
(
id int,
buyer_name varchar(20)
);
INSERT INTO buyers
VALUES (1, 'harry'), (2, 'zoe'), (3, 'rose');
CREATE TABLE grocery
(
id int,
name VARCHAR(20),
id_buyers int
);
INSERT INTO grocery
VALUES (1, 'milk', 1), (2, 'milk', 1), (3, 'ham', 1), (4, 'bread', 2),
(5, 'bread', 2), (6, 'bread', 2), (6, 'milk', 2), (7, 'milk', 2),
(8, 'ham', 3);
CREATE TABLE wanted_output
(
name VARCHAR(20),
stuffed_lists VARCHAR(20)
);
INSERT INTO wanted_output
VALUES ('harry', '2x milk, 1x ham'), ('zoe', '3x bread, 2x milk'),
('rose', '1x ham ');
EDIT :
at this point I have this (not working):
SELECT
buyers.buyer_name,
COALESCE(
STUFF(
(SELECT ' , ' +
CAST( grocery.name AS varchar(max))
from grocery
where grocery.id_buyers = buyers.id
FOR XML PATH('')
), 1, 2, '' ),'')
AS wanted_output
FROM buyers

nvm afther some fideling :
SELECT
buyers.buyer_name,
COALESCE(
STUFF(
(SELECT ' , ' + cast(count(*) as varchar(4)) + ' x ' +
CAST( grocery.name AS varchar(max))
from grocery
where grocery.id_buyers = buyers.id
group by grocery.name
FOR XML PATH('')
), 1, 2, '' ),'')
AS wanted_output
FROM buyers

Related

SQL LEFT JOIN to many categories

Suppose the following easy scenario, where a product row gets connected to one primary category, subcategory, and sub-subcategory.
DECLARE #PRODUCTS TABLE (ID int, DESCRIPTION varchar(50), CAT varchar(30), SUBCAT varchar(30), SUBSUBCAT varchar(30));
INSERT #PRODUCTS (ID, DESCRIPTION, CAT, SUBCAT, SUBSUBCAT) VALUES
(1, 'NIKE MILLENIUM', '1', '10', '100'),
(2, 'NIKE CORTEZ', '1', '12', '104'),
(3, 'ADIDAS PANTS', '2', '27', '238'),
(4, 'PUMA REVOLUTION 5', '3', '35', '374'),
(5, 'SALOMON SHELTER CS', '4', '15', '135'),
(6, 'NIKE EBERNON LOW', '2', '14', '157');
DECLARE #CATS TABLE (ID int, DESCR varchar(100));
INSERT #CATS (ID, DESCR) VALUES
(1, 'MEN'),
(2, 'WOMEN'),
(3, 'UNISEX'),
(4, 'KIDS'),
(5, 'TEENS'),
(6, 'BACK TO SCHOOL');
DECLARE #SUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBCATS (ID, DESCR) VALUES
(10, 'FOOTWEAR'),
(12, 'OUTERWEAR'),
(14, 'SWIMWEAR'),
(15, 'HOODIES'),
(27, 'CLOTHING'),
(35, 'SPORTS');
DECLARE #SUBSUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBSUBCATS (ID, DESCR) VALUES
(100, 'RUNNING'),
(104, 'ZIP TOPS'),
(135, 'FLEECE'),
(157, 'BIKINIS'),
(238, 'PANTS'),
(374, 'JOGGERS');
SELECT prod.ID,
prod.DESCRIPTION,
CONCAT(cat1.DESCR, ' > ', cat2.DESCR, ' > ', cat3.DESCR) AS CATEGORIES
FROM #PRODUCTS AS prod
LEFT JOIN #CATS AS cat1 ON cat1.ID = prod.CAT
LEFT JOIN #SUBCATS AS cat2 ON cat2.ID = prod.SUBCAT
LEFT JOIN #SUBSUBCATS AS cat3 ON cat3.ID = prod.SUBSUBCAT;
Now suppose that the foreign keys on #PRODUCTS table aren't just indices to their respective tables. They are comma-separated indices to more than one categories, subcategories, and sub-subcategories like here.
DECLARE #PRODUCTS TABLE (ID int, DESCRIPTION varchar(50), CAT varchar(30), SUBCAT varchar(30), SUBSUBCAT varchar(30));
INSERT #PRODUCTS (ID, DESCRIPTION, CAT, SUBCAT, SUBSUBCAT) VALUES
(1, 'NIKE MILLENIUM', '1, 2', '10, 12', '100, 135'),
(2, 'NIKE CORTEZ', '1, 5', '12, 15', '104, 374'),
(3, 'ADIDAS PANTS', '2, 6', '27, 35', '238, 374');
DECLARE #CATS TABLE (ID int, DESCR varchar(100));
INSERT #CATS (ID, DESCR) VALUES
(1, 'MEN'),
(2, 'WOMEN'),
(3, 'UNISEX'),
(4, 'KIDS'),
(5, 'TEENS'),
(6, 'BACK TO SCHOOL');
DECLARE #SUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBCATS (ID, DESCR) VALUES
(10, 'FOOTWEAR'),
(12, 'OUTERWEAR'),
(14, 'SWIMWEAR'),
(15, 'HOODIES'),
(27, 'CLOTHING'),
(35, 'SPORTS');
DECLARE #SUBSUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBSUBCATS (ID, DESCR) VALUES
(100, 'RUNNING'),
(104, 'ZIP TOPS'),
(135, 'FLEECE'),
(157, 'BIKINIS'),
(238, 'PANTS'),
(374, 'JOGGERS');
SELECT prod.ID,
prod.DESCRIPTION
--CONCAT(cat1.DESCR, ' > ', cat2.DESCR, ' > ', cat3.DESCR) AS CATEGORIES
FROM #PRODUCTS AS prod
--LEFT JOIN #CATS AS cat1 ON cat1.ID = prod.CAT
--LEFT JOIN #SUBCATS AS cat2 ON cat2.ID = prod.SUBCAT
--LEFT JOIN #SUBSUBCATS AS cat3 ON cat3.ID = prod.SUBSUBCAT;
In this case I want to achieve the following:
Be able to retrieve the respective names of the cats, subcats, sub-subcats, ie. for cats '1, 2' be able to retrieve their names (I tried LEFT JOIN #CATS AS cat1 ON cat1.ID IN prod.CAT but it doesn't work)
Create triplets of the corresponding cats, subcats, sub-subcats, ie. for
cats '1, 2'
subcats '12, 17'
sub-subcats '239, 372'
(after retrieving the appropriate names) create pipe-separated category routes like name of cat 1 > name of subcat 12 > name of sub-subcat 239 | name of cat 2 > name of subcat 17 > name of sub-subcat 372
So, for a row like (1, 'NIKE MILLENIUM', '1, 2', '10, 12', '100, 135'),
I would like to get the following result
ID
DESCRIPTION
CATEGORIES
1
NIKE MILLENIUM
MEN > FOOTWEAR > RUNNING # WOMEN > OUTERWEAR > FLEECE (I had to use # as the delimiter of the two triplets because pipe messed with the table's columns)
In case the user stupidly stores more cat IDs than subcat IDs, or sub-subcat IDs, the query should just match the ones that have a corresponding position match, ie for
cats '1, 2'
subcats '12'
sub-subcats '239, 372'
it should just create one triplet, like name of 1 > name of 12 > name of 239
STRING_SPLIT() does not promise to return the values in a specific order, so it won't work in this case as ordinal position matters.
Use OPENJSON() split the string into separate rows to ensure the values are returned in the same order.
OPENJSON() also returns a key field, so you can join on the row number within each grouping. You'll want an INNER JOIN since your requirement is that all values in that "column" must exist.
Use STUFF() to assemble the various cat>subcat>subsubcat values.
DECLARE #PRODUCTS TABLE (ID int, DESCRIPTION varchar(50), CAT varchar(30), SUBCAT varchar(30), SUBSUBCAT varchar(30));
INSERT #PRODUCTS (ID, DESCRIPTION, CAT, SUBCAT, SUBSUBCAT) VALUES
(1, 'NIKE MILLENIUM', '1, 2', '10, 12', '100, 135'),
(2, 'NIKE CORTEZ', '1, 5', '12, 15', '104, 374'),
(3, 'ADIDAS PANTS', '2, 6, 1', '27, 35, 10', '238, 374, 100'),
(4, 'JOE THE PLUMBER JEANS', '1, 5', '27', '238, 374');
DECLARE #CATS TABLE (ID int, DESCR varchar(100));
INSERT #CATS (ID, DESCR) VALUES
(1, 'MEN'),
(2, 'WOMEN'),
(3, 'UNISEX'),
(4, 'KIDS'),
(5, 'TEENS'),
(6, 'BACK TO SCHOOL');
DECLARE #SUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBCATS (ID, DESCR) VALUES
(10, 'FOOTWEAR'),
(12, 'OUTERWEAR'),
(14, 'SWIMWEAR'),
(15, 'HOODIES'),
(27, 'CLOTHING'),
(35, 'SPORTS');
DECLARE #SUBSUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBSUBCATS (ID, DESCR) VALUES
(100, 'RUNNING'),
(104, 'ZIP TOPS'),
(135, 'FLEECE'),
(157, 'BIKINIS'),
(238, 'PANTS'),
(374, 'JOGGERS');
;
with prod as (
SELECT p.ID,
p.DESCRIPTION
--CONCAT(cat1.DESCR, ' > ', cat2.DESCR, ' > ', cat3.DESCR) AS CATEGORIES
, c.value as CatId
, c.[key] as CatKey
, sc.value as SubCatId
, sc.[key] as SubCatKey
, ssc.value as SubSubCatId
, ssc.[key] as SubSubCatKey
FROM #PRODUCTS p
cross apply OPENJSON(CONCAT('["', REPLACE(cat, ', ', '","'), '"]')) c
cross apply OPENJSON(CONCAT('["', REPLACE(subcat, ', ', '","'), '"]')) sc
cross apply OPENJSON(CONCAT('["', REPLACE(subsubcat, ', ', '","'), '"]')) ssc
where c.[key] = sc.[key]
and c.[key] = ssc.[key]
)
, a as (
select p.ID
, p.DESCRIPTION
, c.DESCR + ' > ' + sc.DESCR + ' > ' + ssc.DESCR as CATEGORIES
, p.CatKey
from prod p
inner join #CATS c on c.ID = p.CatId
inner join #SUBCATS sc on sc.ID = p.SubCatId
inner join #SUBSUBCATS ssc on ssc.ID = p.SubSubCatId
)
select DISTINCT ID
, DESCRIPTION
, replace(STUFF((SELECT distinct ' | ' + a2.CATEGORIES
from a a2
where a.ID = a2.ID
FOR XML PATH(''))
,1,2,''), '>', '>') CATEGORIES
from a
Totally separate answer because of the change to older technology. I think my original answer is still good for folks using current SQL Server versions, so I don't want to remove it.
I don't remember where I got the function. When I found it today it was named split_delimiter. I changed the name, added some comments, and incorporated the ability to have a delimiter that is more than one character long.
CREATE FUNCTION [dbo].[udf_split_string](#delimited_string VARCHAR(8000), #delimiter varchar(10))
RETURNS TABLE AS
RETURN
WITH cte10(num) AS ( -- 10 rows
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL
SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1 UNION ALL SELECT 1
)
, cte100(num) AS ( -- 100 rows
SELECT 1
FROM cte10 t1, cte10 t2
)
, cte10000(num) AS ( -- 10000 rows
SELECT 1
FROM cte100 t1, cte100 t2
)
, cte1(num) AS ( -- 1 row per character
SELECT TOP (ISNULL(DATALENGTH(#delimited_string), 0)) ROW_NUMBER() OVER (ORDER BY (SELECT NULL))
FROM cte10000
)
, cte2(num) AS ( -- locations of strings
SELECT 1
UNION ALL
SELECT t.num + len(replace(#delimiter, ' ', '_'))
FROM cte1 t
WHERE SUBSTRING(#delimited_string, t.num, len(replace(#delimiter, ' ', '_'))) = #delimiter
)
, cte3(num, [len]) AS (
SELECT t.num
, ISNULL(NULLIF(CHARINDEX(#delimiter, #delimited_string, t.num), 0) - t.num, 8000)
FROM cte2 t
)
SELECT [Key] = ROW_NUMBER() OVER (ORDER BY t.num)
, [Value] = SUBSTRING(#delimited_string, t.num, t.[len])
FROM cte3 t;
GO
DECLARE #PRODUCTS TABLE (ID int, DESCRIPTION varchar(50), CAT varchar(30), SUBCAT varchar(30), SUBSUBCAT varchar(30));
INSERT #PRODUCTS (ID, DESCRIPTION, CAT, SUBCAT, SUBSUBCAT) VALUES
(1, 'NIKE MILLENIUM', '1, 2', '10, 12', '100, 135'),
(2, 'NIKE CORTEZ', '1, 5', '12, 15', '104, 374'),
(3, 'ADIDAS PANTS', '2, 6, 1', '27, 35, 10', '238, 374, 100'),
(4, 'JOE THE PLUMBER JEANS', '1, 5', '27', '238, 374');
DECLARE #CATS TABLE (ID int, DESCR varchar(100));
INSERT #CATS (ID, DESCR) VALUES
(1, 'MEN'),
(2, 'WOMEN'),
(3, 'UNISEX'),
(4, 'KIDS'),
(5, 'TEENS'),
(6, 'BACK TO SCHOOL');
DECLARE #SUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBCATS (ID, DESCR) VALUES
(10, 'FOOTWEAR'),
(12, 'OUTERWEAR'),
(14, 'SWIMWEAR'),
(15, 'HOODIES'),
(27, 'CLOTHING'),
(35, 'SPORTS');
DECLARE #SUBSUBCATS TABLE (ID int, DESCR varchar(100));
INSERT #SUBSUBCATS (ID, DESCR) VALUES
(100, 'RUNNING'),
(104, 'ZIP TOPS'),
(135, 'FLEECE'),
(157, 'BIKINIS'),
(238, 'PANTS'),
(374, 'JOGGERS');
;
with prod as (
SELECT p.ID,
p.DESCRIPTION
, c.value as CatId
, c.[key] as CatKey
, sc.value as SubCatId
, sc.[key] as SubCatKey
, ssc.value as SubSubCatId
, ssc.[key] as SubSubCatKey
FROM #PRODUCTS p
cross apply dbo.udf_split_string(cat, ', ') c
cross apply dbo.udf_split_string(subcat, ', ') sc
cross apply dbo.udf_split_string(subsubcat, ', ') ssc
where c.[key] = sc.[key]
and c.[key] = ssc.[key]
)
, a as (
select p.ID
, p.DESCRIPTION
, c.DESCR + ' > ' + sc.DESCR + ' > ' + ssc.DESCR as CATEGORIES
, p.CatKey
from prod p
inner join #CATS c on c.ID = p.CatId
inner join #SUBCATS sc on sc.ID = p.SubCatId
inner join #SUBSUBCATS ssc on ssc.ID = p.SubSubCatId
)
select DISTINCT ID
, DESCRIPTION
, replace(STUFF((SELECT distinct ' | ' + a2.CATEGORIES
from a a2
where a.ID = a2.ID
FOR XML PATH(''))
,1,2,''), '>', '>') CATEGORIES
from a
Well that should do work, i changed your character ">" for "-" just for see the data more simple.
the design of your tables is not perfect but the first try almost never is.
select mainp.ID, mainp.DESCRIPTION, stuff(ppaths.metapaths, len(ppaths.metapaths),1,'') metalinks
from #PRODUCTS mainp
cross apply(
select
(select
c.DESCR + '-' + sc.DESCR + '-' + sbc.DESCR + '|'
from #PRODUCTS p
cross apply (select row_number() over(order by Value) id, Value from split(p.CAT, ','))cat_ids
inner join #cats c on c.ID = cat_ids.Value
cross apply (select row_number() over(order by Value) id, Value from split(p.SUBCAT, ','))subcat_ids
inner join #SUBCATS sc on sc.ID = subcat_ids.Value
and subcat_ids.id = subcat_ids.id
cross apply (select row_number() over(order by Value) id, Value from split(p.SUBSUBCAT, ','))subsubcat_ids
inner join #SUBSUBCATS sbc on sbc.ID = subsubcat_ids.Value
and subsubcat_ids.id = subcat_ids.id
where p.id = mainp.ID
for xml path('')) metapaths
) ppaths
the link for split function
https://desarrolladores.me/2014/03/sql-server-funcion-split-para-dividir-un-string/

How to add pagination to this dynamic sql

I have the following table with its respective data
CREATE TABLE [dbo].[Columns]
(
[ColumnId] INT,
[TableId] INT NOT NULL,
[ColumnName] NVARCHAR(150) NOT NULL,
[Order] INT,
[Key] BIT
)
CREATE TABLE [dbo].[Tables]
(
[TableId] INT,
[TableName] NVARCHAR(200),
[DistrictId] INT
)
CREATE TABLE [dbo].[RowValues]
(
[ColumnId] INT NOT NULL,
[RowNumber] INT NOT NULL,
[Value] NVARCHAR(200) NOT NULL
)
insert into [Columns] values (1, 1, 'StudentName', 1, 1)
insert into [Columns] values (2, 1, 'Grade', 1, 0)
insert into [Columns] values (3, 1, 'Year', 1, 0)
insert into [Columns] values (4, 1, 'Section', 1, 0)
insert into [Columns] values (5, 2, 'TeacherName', 1, 1)
insert into [Columns] values (6, 2, 'Department', 1, 0)
insert into [Tables] values (1, 'Student', 1)
insert into [Tables] values (2, 'Teacher', 1)
insert into [RowValues] values (1, 1, 'Student Alan')
insert into [RowValues] values (2, 1, '99')
insert into [RowValues] values (3, 1, '1st')
insert into [RowValues] values (4, 1, 'Section 1')
insert into [RowValues] values (1, 2, 'Student Alex')
insert into [RowValues] values (2, 2, '98')
insert into [RowValues] values (3, 2, '1st')
insert into [RowValues] values (4, 2, 'Section 1')
insert into [RowValues] values (1, 3, 'Student Alfonso')
insert into [RowValues] values (2, 3, '97')
insert into [RowValues] values (3, 3, '1st')
insert into [RowValues] values (4, 3, 'Section 1')
insert into [RowValues] values (1, 4, 'Student Ben')
insert into [RowValues] values (2, 4, '96')
insert into [RowValues] values (3, 4, '1st')
insert into [RowValues] values (4, 4, 'Section 1')
insert into [RowValues] values (1, 5, 'Student Cathy')
insert into [RowValues] values (2, 5, '95')
insert into [RowValues] values (3, 5, '1st')
insert into [RowValues] values (4, 5, 'Section 1')
insert into [RowValues] values (5, 1, 'Teacher Tesso')
insert into [RowValues] values (6, 1, 'Biology Dept')
insert into [RowValues] values (5, 2, 'Teacher Marvin')
insert into [RowValues] values (6, 2, 'Math Dept')
I wanted to be able to sort the dynamic column
example sort by 'StudentName' ASC it would sort data using column returning
When sorting by StudentName:
StudentName Grade Year Section
'Student Alan' 99 '1st' 'Section 1'
'Student Alex' 98 '1st' 'Section 1'
'Student Alfonso' 97 '1st' 'Section 1'
.
.
.
When sorting by Grade ASC:
StudentName Grade Year Section
'Student Cathy' 95 '1st' 'Section 1'
'Student Ben' 96 '1st' 'Section 1'
'Student Alfonso' 97 '1st' 'Section 1'
.
.
.
When sorting by TeacherName ASC (different table)
TeacherName Department
'Teacher Marvin' 'Math Dept'
'Teacher Tesso' 'Biology Dept'
.
.
.
I have manage to accomplish this.
The problem is adding Pagination to my dynamic SQL string.
This is my stored procedure
CREATE PROCEDURE [dbo].[usp_DynamicSearch_Paged]
(#districtId INT,
#searchTerm NVARCHAR(max),
#pageNumber INT = 1,
#pageSize INT = 10,
#sortColumn NVARCHAR(20),
#sortDirection INT)
AS
BEGIN
DECLARE #columns nvarchar(max),
#sql nvarchar(max),
#rows int
SET #rows = (#pageNumber - 1) * #pageSize;
SELECT
#columns = (SELECT ',' + QUOTENAME(ColumnName)
FROM Tables AS T
INNER JOIN Columns AS C ON T.TableId = C.TableId
WHERE T.districtId = #districtId
ORDER BY C.[Order]
FOR XML PATH(''))
SELECT
#columns = (SELECT ',' + QUOTENAME(ColumnName)
FROM Tables AS T
INNER JOIN Columns AS C ON T.TableId = C.TableId
WHERE T.districtId = #districtId
ORDER BY C.[Order]
FOR XML PATH(''))
SELECT [Columns] = REPLACE(REPLACE(value,'[',''),']','')
FROM STRING_SPLIT(STUFF(#Columns, 1, 1, ''),',')
SET #sql = N'
SELECT * INTO #Fields FROM (
SELECT
ROW_NUMBER() OVER (PARTITION BY ColumnName ORDER BY (SELECT NULL)) RN,
districtId,
ColumnName
, V.[Value]
FROM Tables AS T
INNER JOIN Columns AS C
ON T.TableId = C.TableId
LEFT OUTER JOIN RowValues AS V
ON C.ColumnId = V.ColumnId
) t
PIVOT (
MIN([Value])
FOR [ColumnName]
IN ('
+ STUFF(#Columns, 1, 1, '') +
')
) AS PivotTable
DECLARE #KeyColumnName NVARCHAR(100)
SELECT #KeyColumnName = ColumnName
FROM Tables AS T
INNER JOIN Columns AS C
ON T.TableId = C.TableId
WHERE T.districtId = ' + CAST(#districtId AS VARCHAR) + '
AND C.IsKey = 1
DECLARE #sql NVARCHAR(MAX)
SET #SQL = ''
SELECT *
FROM #Fields
WHERE '' + #KeyColumnName + '' LIKE '''''+ #searchTerm +'%''''
''
OFFSET ('+CAST(#rows AS VARCHAR)+') ROWS
FETCH NEXT ' +CAST(#pageSize AS VARCHAR) +' ROWS ONLY;
EXEC sp_EXECUTESQL #sql
'
EXEC sp_executesql #sql
END
I just added the
OFFSET ('+CAST(#rows AS VARCHAR)+') ROWS
FETCH NEXT ' +CAST(#pageSize AS VARCHAR) +' ROWS ONLY;
EXEC sp_EXECUTESQL #sql
and now it doesn't work
The OFFSET and FETCH clauses are the options of the ORDER BY clause. They allow you to limit the number of rows to be returned by a query.
https://www.sqlservertutorial.net/sql-server-basics/sql-server-offset-fetch/
I think you need to declare ORDER BY

TSQL - Select Latest Date by 2 Type

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

Query response in JSON format without column name

My table schema is something like this,
DECLARE #mytable AS TABLE(ID INT, EmpName VARCHAR(10), Age INT);
INSERT INTO #mytable
VALUES
(1, 'a', 1),
(2, 'b', 2),
(3, 'c', 3),
(4, 'd', 4),
(5, 'e', 5),
(6, 'f', 6),
(7, 'g', 7),
(8, 'h', 8),
(9, 'i', 9),
(10, 'j', 10);
Initially, my procedure was returning with data as
SELECT ID, EmpName, Age FROM #mytable;
After processing the data, to the web page is sent as
[{1,"a",1},
{2,"b",2},
{3,"c",3},
{4,"d",4},
{5,"e",5},
{6,"f",6},
{7,"g",7},
{8,"h",8},
{9,"i",9},
{10,"j",10}]
If I use
SELECT ID, EmpName, Age
FROM #mytable
FOR JSON AUTO;
the result will be like
[{"ID":1,"EmpName":"a","Age":1},
{"ID":2,"EmpName":"b","Age":2},
{"ID":3,"EmpName":"c","Age":3},
{"ID":4,"EmpName":"d","Age":4},
{"ID":5,"EmpName":"e","Age":5},
{"ID":6,"EmpName":"f","Age":6},
{"ID":7,"EmpName":"g","Age":7},
{"ID":8,"EmpName":"h","Age":8},
{"ID":9,"EmpName":"i","Age":9},
{"ID":10,"EmpName":"j","Age":10}]
So what I need to get is the same response but without column name, as front-end lib uses the JSON array without keys.
SQL Server version 2012 is used.
I hope I am clear on my end. Thanks.
Try this:
SELECT STUFF
(
(
SELECT CONCAT(',{', ID, ', "', EmpName, '", ', age, '}')
FROM #mytable
FOR XML PATH(''), TYPE
).value('.', 'varchar(max)')
,1
,1
,'['
) + ']';
You could use the "select to a variable" trick to build the string.
declare #JsonesceString varchar(max);
select #JsonesceString = concat(#JsonesceString+','+char(10),'{',ID,',"',EmpName,'",',age,'}')
from #mytable
order by ID;
select concat('[',#JsonesceString,']') as Result;
Returns the value:
[{1,"a",1},
{2,"b",2},
{3,"c",3},
{4,"d",4},
{5,"e",5},
{6,"f",6},
{7,"g",7},
{8,"h",8},
{9,"i",9},
{10,"j",10}]

Subqueries With Multiple Tables

Good day, need your help on my Vehicle Inspection Database. You can see below the structure, you can see it also in here http://sqlfiddle.com/#!3/4ab7e . What I need from this is to extract The Number of Vehicles With Atleast One (1) Defect or Violation Per PROJECT. In the schema below The Total for Project 4 = two (2) vehicles AND Project 9 = 1 vehicle.
Columns Needed are [Project_Name],[Vehicle_Type],[yy],[mm],[Total]
-- Vehicle Inspection Database --
-- Vehicle_Type Table
CREATE TABLE VehicleType
([VehicleTypeId] int,
[Type] varchar (36));
INSERT INTO VehicleType ([VehicleTypeId],[Type])
VALUES (1, 'Light Vehicle'),
(2, 'Tanker'),
(3, 'Goods');
-- Car Table
CREATE TABLE Vehicle
([VehicleID] varchar(36),
[PlateNo] varchar(36),
[VehicleTypeId] int,
[Project] int);
INSERT INTO Vehicle ([VehicleID], [PlateNo],[VehicleTypeId], [Project])
VALUES('A57D4151-BD49-4B44-AF10-000F1C298E05', '8112AG', 1, 4),
('C7095628-AE88-4DD0-A4FD-00363EAB767F', '60070 AD2', 2, 9),
('E714CCD7-E56C-46A8-89D5-003CA5BF6094', '68823 AD1', 3, 9);
-- Event Table
CREATE TABLE Event
([EventID] int,
[VehicleID] varchar(36),
[EventTime] smalldatetime,
[TicketStatus] varchar (10)) ;
INSERT INTO Event([EventID], [VehicleID], [EventTime], TicketStatus)
VALUES (1, 'A57D4151-BD49-4B44-AF10-000F1C298E05', '20130701', 'Open'),
(2, 'A57D4151-BD49-4B44-AF10-000F1C298E05', '20130702', 'Close'),
(3, 'A57D4151-BD49-4B44-AF10-000F1C298E05', '20130703', 'Close'),
(4, 'C7095628-AE88-4DD0-A4FD-00363EAB767F','20130705', 'Open'),
(5, 'C7095628-AE88-4DD0-A4FD-00363EAB767F','20130710', 'Open');
-- Event_Defects Table
CREATE TABLE EventDefects
([EventDefectsID] int,
[EventID] int,
[Status] varchar(15),
[DefectID] int) ;
INSERT INTO EventDefects ([EventDefectsID], [EventID], [Status], [DefectID])
VALUES
-- 1st Inspection for PlateNo. 8112AG
(1, 1, 'YES', 1),
(2, 1, 'NO', 2),
(3, 1, 'YES',3),
(4, 1, 'N/A', 4),
(5, 1, 'N/A', 5),
-- 2nd Inspection for PlateNo. 8112AG
(6, 2, 'NO', 1),
(7, 2, 'NO', 2),
(8, 2, 'NO', 3),
(9, 2, 'N/A', 4),
(10,2, 'N/A', 5),
-- 3rd Inspection for PlateNo. 8112AG
(11, 3, 'NO', 1),
(12, 3, 'NO', 2),
(13, 3, 'NO', 3),
(14, 3, 'NO', 4),
(15, 3, 'NO', 5),
-- 1st Inspection for PlateNo. 60070 AD2
(16, 3, 'NO', 1),
(17, 3, 'NO', 2),
(18, 3, 'NO', 3),
(19, 3, 'N/A', 4),
(20, 3, 'N/A', 5);
-- Defects Table
CREATE TABLE Defects
([DefectID] int,
[DefectsName] varchar (36),
[DefectClassID] int) ;
INSERT INTO Defects ([DefectID], [DefectsName], [DefectClassID])
VALUES (1, 'TYRE', 1),
(2, 'BRAKING SYSTEM', 1),
(3, 'MIRRORS AND WINDSCREEN', 2),
(4, 'OVER SPEEDING', 3),
(5, 'NOT WEARING SEATBELTS', 3);
-- Defect_Class Table
CREATE TABLE DefectClass
([Description] varchar (15),
[DefectClassID] int) ;
INSERT INTO DefectClass ([DefectClassID], [Description])
VALUES (1, 'CATEGORY A'),
(2, 'CATEGORY B'),
(3, 'CATEGORY C');
Do all the joins as inner joins... and it'll eliminate records that are empty.
Can you check if this works for you?
SELECT Vehicle.VehicleID from Vehicle
INNER JOIN Event ON Vehicle.VehicleID = Event.VehicleID
INNER JOIN EventDefects ON EventDefects.EventID = Event.EventID
INNER JOIN Defects ON EventDefects.DefectID = Defects.DefectID
GROUP BY Vehicle.VehicleID;