SQLSERVER Combine multiple lines into 1 row - sql-server

I have the following tables:
Product_Order
Order_Num Order_Date
1 10/12/2017
2 10/31/2017
3 11/01/2017
Product_Order_Dtl
Order_Num Product_Desc
1 Toy_01
1 Toy_02
1 Toy_03
2 Toy_01
2 Toy_05
3 Toy_01
I am trying to update the Product Order Table to list all the products associated with that order into a new column called Product_List. Just like the following:
Product_Order
Order_Num Order_Date Product_List
1 10/12/2017 Toy_01, Toy_02, Toy_03
2 10/31/2017 Toy_01, Toy_05
3 11/01/2017 Toy_01
Is there a way to do that using an update statement? I am using a version of SQL 2012.

you can use below query
SELECT A.Order_Num, A.Order_Date, STUFF((SELECT ',' + Product_Desc
FROM Product_Order_Dtl C
where C.Order_Num=A.Order_Num
FOR XML PATH('')), 1, 1, '') AS Product_List
from Product_Order A
inner join Product_Order_Dtl B on A.Order_Num =B.Order_Num
group by A.Order_Num,A.Order_Date

This will do it:
SELECT
PO.Order_Num
, PO.Order_Date
,
STUFF
(
(
SELECT ', ' + POD.Product_Desc
FROM Product_Order_Dtl POD
WHERE POD.Order_Num = PO.Order_Num
ORDER BY POD.Product_Desc
FOR XML PATH ('')
), 1, 2, ''
) Product_List
FROM Product_Order PO

Related

How to use alias in where clause in SQL Server

I have following query and i am getting perfect result what i want but i want to use stManufacturerPartReference alias in where clause condition Like following second query but it gives me error.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted <> 1
AND flgIsHistoricItem <> 1 AND (product.inCompanyId = 1) )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;
i want to use stManufacturerPartReference in Where Clause Like Following.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted <> 1
AND flgIsHistoricItem <> 1 AND (product.inCompanyId = 1) AND stManufacturerPartReference LIKE '%ABC DEF%' )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;
But it Gives me Error "Invalid column name 'stManufacturerPartReference'."
So how can i use alias in where clause please help.
thanks.
I would do instead :
SELECT *, STUFF(stManufacturerPartReference, 1, 1, '') AS stManufacturerPartReference
FROM . . . .
. . . . CROSS APPLY
( SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM JOIN
tblProducts Product
ON PM.inProductId = Product.inProductId JOIN
tblManufacturers M
ON M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
FOR XML PATH('')
) tt(stManufacturerPartReference)
WHERE . . . AND
stManufacturerPartReference LIKE '%ABC DEF%';
You need to learn about the order of execution in a SQL query: https://sqlbolt.com/lesson/select_queries_order_of_execution
WHERE comes immediately after FROM, and therefore any aliases are not available to filter on.
As it's wrapped in a CTE, filter on stManufacturerPartReference in the query after it.
WITH ProductsCTE (inProductId, inCategoryId, stCategory, stManufacturers, inCompanyId, stERPId,stManufacturerPartReference,
stProductName, stProductNumber, stModel, stFileLink, stImage, dcPrice,dcStandardPrice, dcOnHandQty,dcQtyOnPO,dtEstimatedShipDate, dcWeight, inSyncStatus, dtLastSyncDate,
inErrorRetry,flgIsActive, flgIsDeleted, inCreatedBy, inModifiedBy, dtModificationDate, dtCreationDate, inRecordCount)
AS (
SELECT
product.inProductId,
product.inCategoryId,
product.stCategory,
product.stManufacturers,
product.inCompanyId,
product.stERPId,
product.stProductName,
STUFF((SELECT ', ' + PM.stManufacturerPartReference
FROM tblProductManufacturers PM
JOIN tblProducts Product on PM.inProductId = Product.inProductId
JOIN tblManufacturers M on M.inManufacturerId = PM.inManufacturerId
WHERE PM.inProductId=product.inProductId
ORDER BY M.stManufacturer
FOR XML PATH('')), 1, 1, '') as stManufacturerPartReference,
product.stProductNumber,
product.stModel,
product.stFileLink,
product.stImage,
product.dcPrice,
product.dcStandardPrice,
product.dcOnHandQty,
product.dcQtyOnPO,
product.dtEstimatedShipDate,
product.dcWeight,
product.inSyncStatus,
product.dtLastSyncDate,
product.inErrorRetry,
product.flgIsActive,
product.flgIsDeleted,
product.inCreatedBy,
product.inModifiedBy,
product.dtModificationDate,
product.dtCreationDate,
CAST((COUNT(product.inProductId) OVER()) AS BIGINT) AS inRecordCount
FROM tblProducts Product WITH (NOLOCK)
WHERE 1=1
AND product.flgIsDeleted 1
AND flgIsHistoricItem 1 AND (product.inCompanyId = 1) )
SELECT P.inProductId,
P.inCategoryId,
P.stCategory,
P.stManufacturers,
P.stManufacturerPartReference,
P.inCompanyId,
P.stERPId,
P.stProductName,
P.stProductNumber,
P.stModel,
P.stFileLink,
P.stImage,
P.dcPrice,
P.dcStandardPrice,
P.dcOnHandQty,
P.dcQtyOnPO,
P.dtEstimatedShipDate,
P.dcWeight,
P.inSyncStatus,
P.dtLastSyncDate,
P.inErrorRetry,
P.flgIsActive,
P.flgIsDeleted,
P.inCreatedBy,
P.inModifiedBy,
P.dtModificationDate,
P.dtCreationDate,
P.inRecordCount
FROM ProductsCTE P
WHERE P.stManufacturerPartReference LIKE '%ABC DEF%'
ORDER BY stCategory ASC
OFFSET (1 - 1) * 1000 ROWS
FETCH NEXT 1000 ROWS ONLY;
You have to use outer apply or cross apply (select .. AS stManufacturerPartReference) and if your server is 2017 you could use String_AGG function to get list of values instead of for xml clause.

T-SQL side-by-side coupling of data at the end

In the following screenshot, I would like to merge the data in the YorumYapanAdsoyad column on a single line.
enter image description here
It should be this way;
8 | Fiat Linea 1.3 Multijet | Ahmet, Selami
12 | Vw Golf | Ertem, Selim
Thanks for the help ;)
Try this ,for earlier versions on SQL (2016 and down)
;WITH Tmp (UrunId, Araclar , YorumYapanSoyad) as
(
SELECT 8 , 'Fiat Line 1.3 Multijet' , 'Ahmet'
UNION ALL
SELECT 8 , 'Fiat Line 1.3 Multijet' , 'Selami'
UNION ALL
SELECT 12 , 'Vw Golf' , 'Ertem'
UNION ALL
SELECT 12 , 'Vw Golf' , 'Selim'
)
SELECT UrunId , Araclar ,
(SELECT STUFF(
(SELECT ', ' + YorumYapanSoyad
FROM Tmp b
WHERE B.Araclar = T.Araclar
AND b.UrunId = t.UrunId
FOR XML PATH (''),TYPE).value('.','nvarchar(max)'),1,2,'')
) YorumYapanSoyad
FROM Tmp t
GROUP BY UrunId , Araclar
Try this
DECLARE #Table TABLE (ID INT,Araclar varchar(100),YorumYapan varchar(20))
INSERT INTO #Table
SELECT 8 , 'Fiat Linea 1.3 Multijet' , 'Ahmet' UNION ALL
SELECT 8 , 'Fiat Linea 1.3 Multijet' , 'Selami' UNION ALL
SELECT 12 , 'Vw Golf' , 'Ertem' UNION ALL
SELECT 12 , 'Vw Golf' , 'Selim'
SELECT DISTINCT ID
,Araclar
,STUFF((SELECT ', '+YorumYapan
FROM #Table i WHERE i.ID=o.ID FOR XML PATH ('')),1,1,'') AS YorumYapan
FROM #Table o
Result
ID Araclar YorumYapan
------------------------------------------
8 Fiat Linea 1.3 Multijet Ahmet, Selami
12 Vw Golf Ertem, Selim
This is the recipe I use. As I don't know your table names, I made this example using sys.tables and sys.columns. Basically, the function STUFF is your friend here.
SELECT
t.name,
STUFF
(
(
SELECT ', ' + c.name
FROM sys.columns c
WHERE c.object_id = t.object_id
FOR XML PATH('')
),
1, /*string start*/
2, /*string length*/
'' /*replaceWith*/
)
FROM sys.tables t

Dynamic Columns - SQL Server 2012

Having two tables, I want to convert some rows to columns. My database engine is Microsoft SQL Server. The image below illustrates my desired result.
Your question is not so clear, but it seems you want to use SQL PIVOT
Sample Data
DECLARE #tblModule TABLE(modId INT,name VARCHAR(200))
DECLARE #tblProfile TABLE(id INT,modId INT,profil VARCHAR(200))
INSERT INTO #tblModule
SELECT 1,'Manteniminento' UNION
SELECT 2 , 'Soporte'
INSERT INTO #tblProfile
SELECT 1,1,'Administrador' UNION
SELECT 2,2 , 'Empleado' UNION
SELECT 3,1 , 'Empleado' UNION
SELECT 4,1 , 'Empleado' UNION
SELECT 5,1 , 'Administrador' UNION
SELECT 6,1 , 'Administrador'
Main query
SELECT name,SUM([Administrador]) AS Administrador, SUM([Empleado]) AS Empleado
FROM
(SELECT id,p.modId,m.name,p.profil
FROM #tblProfile p
INNER JOIN #tblModule m ON m.modId = p.modId) AS SourceTable
PIVOT
(
COUNT(modId)
FOR profil IN ([Administrador], [Empleado])
) AS PivotTable
GROUP BY name
Result
name Administrador Empleado
Manteniminento 3 2
Soporte 0 1
I found the solution to what I needed. I share with you I made use of SQL STUFF:
SELECT A.codEmpresa
,A.nomEmpresa
,A.codSistema
,A.nomSistema
,A.codPerfil
,A.nomPerfil
,modulos = STUFF((SELECT DISTINCT ', ' + M.nomModulo
FROM smpseg.[0004] R
JOIN smpseg.[0014] SMOP
ON SMOP.codSistema = R.codSistema
AND SMOP.codModulo = R.codModulo
AND SMOP.codPerfil = A.codPerfil
AND SMOP.objDefault = CAST(1 AS BIT)
JOIN smpseg.[0011] O
ON O.codSistema = SMOP.codSistema
AND O.codModulo = SMOP.codModulo
AND O.codObjeto = SMOP.codObjeto
JOIN smpseg.[0010] M
ON M.codSistema = O.codSistema
AND M.codModulo = O.codModulo
WHERE R.codUsuario = #p_codUsuario
FOR XML PATH('')), 1, 2, '') FROM smpseg.[0004] A
JOIN smpseg.[0016] U
ON U.codUsuario = A.codUsuario

Issue in complicated join

I have 4 tables
tbLicenceTypesX (2 Fields)
LicenceTypes
LicenceTypesX
tbLicenceTypesX (Contains data like)
1 - Medical Licence
2 - Property
3 - Casualty
4 - Trainning Licence
tbProduct (3 feilds)
Product
ProductX
CompanyId (F.K)
LicenceTypes(F.K)
tbProduct (Contains data like)
1 - T.V - 10 - 2
2 - A.C - 30 - 3
3 - Mobiles - 40 -4
tbLicence (3 feilds)
Licence
LicenceTypesNames
AgentId
tbLicence (Contains data like)
1 - Property, Casualty - 23
2 - Trainning Licence, Casualty - 34
Now I have to Fetch Product and ProductX from tbProduct whose LicenceTypes matches with Agent's Licence in tbLicence in a Company.
For e.g: I have to fetch T.V Whose Licence Types is 2("Property") and Company Id is 10 which should be assigned to Agent where Agent Id is 23 and Whose LicenceTypesNames should also contains "Property"
I want to fetch something like
#CompanyId int,
#AgentId int
As
SELECT p.ProductX,p.Product
from tbProduct p
inner join tbLicence l on p.LicenceTypes = l.LicenceTypesNames<its corresponding Id>
inner join tbProduct c on c.Product =p.Product
where
c.CompanyId=#CompanyId
and l.AgentId=#AgentId
Please help me!!!
You can use XML and CROSS APPLY to Split the comma separated values and JOIN with tbProduct. The LTRIM and RTRIM functions are used to trim the comma separated values if they have excessive empty space. The below code gives you the desired output.
DECLARE #CompanyId int = 30, #AgentId int = 23
;WITH CTE AS
(
SELECT AgentId, TCT.LicenceTypes FROM
(
SELECT AgentId, LTRIM(RTRIM(Split.XMLData.value('.', 'VARCHAR(100)'))) LicenceTypesNames FROM
(
SELECT AgentID, Cast ('<M>' + REPLACE(LicenceTypesNames, ',', '</M><M>') + '</M>' AS XML) AS Data
FROM tbLicence
) AS XMLData
CROSS APPLY Data.nodes ('/M') AS Split(XMLData)
)
AS LTN
JOIN tbLicenceTypesX TCT ON LTN.LicenceTypesNames = tct.LicenceTypesX
)
SELECT p.ProductX,p.Product
FROM tbProduct P
JOIN CTE c on p.LicenceTypes = c.LicenceTypes
WHERE CompanyId = #CompanyId
AND AgentId = #AgentId
Sql Fiddle Demo

how to write nested query

I have a table named Options. have Three fields Caption, OptionID, ParentOptionID.
it contains some records like :
OptiondID Caption ParentOptionID
1 Entry 0
2 Sale 1
3 Sale Invoice 2
----------------------------------------------
I want the result as :
OptiondID Caption ParentOptionID
1 Entry 0
2 Entry - Sale 1
3 Entry - Sale - Sale Invoice 2
-----------------------------------------------
Option Caption of its parent option - added in current Options Caption, and it should be nested.
This is the query that I have tried:
;with MyRelation as (
-- Anchor member definition
select OID, Cast(Caption as Varchar(1000)) as Caption, POID, iid
from #tmpOptions as e
UNION ALL
-- Recursive member definition
select e.OID, Cast(e.Caption + '-' + r.Caption as Varchar(1000)) as Caption, e.POID, e.iid
from #tmpOptions as e join MyRelation R on e.POID = R.OID
)
-- Statement that executes the CTE
select OID, Caption, POID, iid
from MyRelation
Could you tried with below query
;WITH MyRelation AS (
SELECT OptiondID, convert(varchar(max), Caption) AS Caption, ParentOptionID
FROM Options
WHERE ParentOptionID = 0
UNION ALL
SELECT Options.OptiondID, MyRelation.Caption + ' - ' + Options.Caption, Options.ParentOptionID
FROM Options
INNER JOIN MyRelation ON Options.ParentOptionID = MyRelation.OptiondID
WHERE Options.ParentOptionID <> 0
)
SELECT * FROM MyRelation

Resources