Joining condition failing - sql-server

I have 2 tables. One is #crecs that stores list of CIDs and a #temp1 that stores clone CVIDs. For the ID in the Crecs table, I want to loop through the #temp1 table to find max(CVID) and pull out the date of the Cloned CVID for that CID based on a condition.
I have boiled down the requirement to below tables:
create table #temp1(cid int,cvid int,flag varchar(5), date1 date, clone int)
insert into #temp1
values ('43','1001','A','1/1/2015',null),
('43','1002','R','2/1/2015',1001),
('43','1003','R','3/1/2015',1002),
('43','1004','R','4/1/2015',1003)
create table #crecs(cid int)
insert into #crecs values(43),(44),(45)
select * from #crecs
select * from #temp1
My query:
select t2.cid,max(t2.cvid),t2.clone,t1.cvid,t1.date1
from #temp1 t2 , #temp1 t1
join #crecs c on c.cid = t1.cid
where t2.clone = t1.cvid
and t1.clone is null and t1.flag = 'A'
group by t2.cid,t2.cvid,t2.clone,t1.cvid,t1.date1
drop table #temp1,#crecs
Desired output:
Below is my rextester link:
http://rextester.com/GSIG28211
Any help?!

You can use a recursive CTE to travel through each clone, then retrieve the last level with MAX() and display it's record.
;WITH RecursiveClones AS
(
SELECT
CID = C.cid,
OriginalCVID = T.cvid,
ClonedCVID = T.cvid,
Level = 0
FROM
#crecs AS C
LEFT JOIN #temp1 AS T ON C.cid = T.cid
WHERE
NOT EXISTS (SELECT 'does not have a clone' FROM #temp1 AS X WHERE X.cvid = T.clone)
UNION ALL
SELECT
CID = R.cid,
OriginalCVID = R.OriginalCVID,
ClonedCVID = T.cvid,
Level = R.Level + 1
FROM
RecursiveClones AS R
INNER JOIN #temp1 AS T ON R.ClonedCVID = T.clone
),
LastCloneByCID AS
(
SELECT
R.CID,
MaxLevel = MAX(R.Level)
FROM
RecursiveClones AS R
GROUP BY
R.CID
)
SELECT
L.CID,
R.ClonedCVID,
R.OriginalCVID,
T.date1
FROM
LastCloneByCID AS L
LEFT JOIN RecursiveClones AS R ON
L.CID = R.CID AND
L.MaxLevel = R.Level
LEFT JOIN #temp1 AS T ON
T.cid = L.CID AND
T.CVID = R.OriginalCVID

Related

Insert numbers in table in sequence but without IDENTITY set

I have few tables, in one of them I am doing load from excel file and then i am doing insert from select
In target table i have column id which doesn't have IDENTITY on it and i cannot create it, so I used ROW_NUMBER() in my select for INSERT,
however now I am having problem, when next time I'm doing load from file into my temp table from which I am selection data for INSERT row number starts from 1 and if iam trying to do insert i am getting error obout problems with Primary key/ So i need to add ID based on id which is already in target table
for example if in target table last record 1000
first record from new Insert has to have id 1001
INSERT INTO table1
( Id ,
OkeiId ,
OkpdId ,
OkvedId ,
)
SELECT
-- (SELECT MAX (id) FROM table1) AS 'last id in table',
ROW_NUMBER() OVER ( ORDER BY ( SELECT 0 ) ) AS Row , -- Id - int
a.[Id] AS OkeId , - int
c.[Id] AS OkpId , - int
D.[Id] AS OkvId , - int
FROM [dbo].#table b
LEFT OUTER JOIN table2 a ON b.F6 = a.[NationalSymbol]
LEFT OUTER JOIN table3 c ON b.F4 = c.Code
LEFT OUTER JOIN table4 D ON b.F5 = D.Code
LEFT OUTER JOIN table1 f ON b.f1 = f.Code
WHERE f.code IS NULL
any Ideas how to continue insert id in sequence? I CANNOT use IDENTITY on this table. I hope you can understand my explanetions
INSERT INTO table1
( Id ,
OkeiId ,
OkpdId ,
OkvedId
)
SELECT
-- (SELECT MAX (id) FROM table1) AS 'last id in table',
a.last_id + ROW_NUMBER() OVER ( ORDER BY ( SELECT 0 ) ) AS Row , -- Id - int
a.[Id] AS OkeiId , -- OkeiId - int
c.[Id] AS OkpdId , -- OkpdId - int
D.[Id] AS OkvedId -- OkvedId - int
FROM [dbo].#table b
LEFT OUTER JOIN table2 a ON b.F6 = a.[NationalSymbol]
LEFT OUTER JOIN table3 c ON b.F4 = c.Code
LEFT OUTER JOIN table4 D ON b.F5 = D.Code
LEFT OUTER JOIN table1 f ON b.f1 = f.Code
CROSS JOIN (SELECT MAX (id) AS last_id FROM table1 ) a
WHERE f.code IS NULL
and some tests:
CREATE TABLE #a
(
a INT PRIMARY KEY,
aa int
)
CREATE TABLE #b
(
b int
)
INSERT INTO #a VALUES(1,1);
INSERT INTO #b VALUES(1);
INSERT INTO #b VALUES(2);
INSERT INTO #b VALUES(3);
INSERT INTO #b VALUES(4);
INSERT INTO #b VALUES(5);
INSERT INTO #a
SELECT last_id + ROW_NUMBER() OVER(ORDER BY b.b), b.b FROM #b b CROSS JOIN (SELECT MAX(a) last_id FROM #a) a
If you're unable to use IDENTITY for some reason and are on SQL Server 2012+, consider sequence numbers. They can be used with multiple columns/tables and are generally more flexible than IDENTITY. See below for examples of creation and use.
Sequence create
CREATE SEQUENCE TestSequence
AS INTEGER
START WITH 1
INCREMENT BY 1;
Sequence use
CREATE TABLE TestTable
(
TestId INTEGER NOT NULL,
TestColumn CHAR(1) NULL
);
INSERT INTO TestTable (TestId, TestColumn)
VALUES (NEXT VALUE FOR TestSequence, 'A');
SQL Fiddle

Need to insert a record if count = 0 else update the record

I need to write a query where i need to check the count record if count is 0, I am suppose to insert a record else update the record
If I do the same thing using cursor, it works fine but the same thing doesnt work with no cursor
Here is my query (with no cursor)
---Without cursor
INSERT INTO [dbo].Products_Del (product_Id, product_Del_startdate)
SELECT f.product_Id, min(cast(product_startdate as datetime)) AS orig_order_date FROM [dbo].Products f
inner join [dbo].Products_Del ac on f.product_Id = ac.product_Id
WHERE Product_Status = 'ORDERED'
AND product_startdate != '.'
AND (select COUNT(*) FROM products f1
INNER JOIN dbo.Products_Del ac on f1.product_Id = ac.product_Id
where f1.product_Id = f.product_Id) = 0
GROUP BY f.product_Id --order by product_Id
-- Update if exists
;with cts
AS (
SELECT product_Id , min(cast(product_startdate as datetime)) as orig_date from [dbo].Products f
WHERE product_Id in (select product_Id from Products_Del)
and Product_Status = 'ORDERED'
AND product_startdate != '.' -- ignore rows where date is unknown
AND (select COUNT(*) FROM Products f1
INNER JOIN dbo.Products_Del ac on f1.Product_id = ac.Product_id
where f1.product_Id = f.product_Id) = 1
GROUP BY product_Id
)
UPDATE ac
SET ac.product_Del_startdate = cts.orig_date
FROM Products_Del ac
INNER JOIN cts ON ac.product_Id = cts.product_Id
But this works good (with cursor)
DECLARE #v_count INT
DECLARE #c_product_id INT
DECLARE #c_product_date DATETIME
DECLARE cursor1 CURSOR FOR
SELECT product_id,
min(cast(product_startdate as DATETIME)) AS orig_order_date
FROM [dbo].Products
WHERE Product_Status = 'ORDERED'
AND product_startdate != '.' -- ignore rows where date is unknown
GROUP BY product_id
--order by product_id
OPEN cursor1
FETCH NEXT FROM cursor1 INTO #c_product_id,#c_product_date
WHILE(##FETCH_STATUS = 0)
BEGIN
SELECT #v_count = COUNT(*)
FROM [dbo].Products_Del
WHERE product_Id = #c_product_id
IF #v_count = 1
BEGIN
-- If so, plug the date into that row.
UPDATE [dbo].Products_Del
SET product_Del_startdate = #c_product_date
WHERE product_Id = #c_product_id
END
ELSE
BEGIN
-- If not, then create a new row in the aircraft_delivery_status table
IF #v_count = 0
BEGIN
INSERT INTO [dbo].Products_Del
(product_Id, product_Del_startdate)
VALUES (#c_product_id, #c_product_date)
END
END
FETCH NEXT FROM cursor1 INTO #c_product_id,#c_product_date
END
CLOSE cursor1
DEALLOCATE cursor1
SQL Fiddle link with schema
http://sqlfiddle.com/#!6/a7d0d/1
In the insert statement you have incorrect join
inner join [dbo].Products_Del ac on f.product_Id = ac.product_Id
just remove it
In the update statement (or ctp) you have incorrect condition :
(select COUNT(*) FROM Products f1
INNER JOIN dbo.Products_Del ac on f1.Product_id = ac.Product_id
where f1.product_Id = f.product_Id) =
1
because you have multiple rows with the same product_id in products table you can get more than one row in this subquery
Also I can suggest following query:
WITH OrderedProducts as(
SELECT p.product_id as product_id,
min(cast(product_startdate as datetime)) as start_date
FROM [dbo].[Products] as p
WHERE p.Product_Status = 'ORDERED'
AND p.Product_startdate != '.'
GROUP BY p.product_id
)
UPDATE pd
SET pd.product_Del_startdate = op.start_date
FROM Products_Del pd
INNER JOIN OrderedProducts as op ON pd.product_Id = op.product_Id
;WITH OrderedProducts as(
SELECT p.product_id as product_id,
min(cast(product_startdate as datetime)) as start_date
FROM [dbo].[Products] as p
WHERE p.Product_Status = 'ORDERED'
AND p.Product_startdate != '.'
GROUP BY p.product_id
)
INSERT INTO [dbo].Products_Del (product_Id, product_Del_startdate)
SELECT op.product_id, op.start_date FROM OrderedProducts as op
WHERE NOT EXISTS (
SELECT pd.product_id FROM [dbo].Products_Del as pd
WHERE pd.product_id = op.product_id )

How to update and insert with list of values in sql

I get a list of values from the select query. From the list, I am checking whether the items in the list is available in the table. If the values exist, I need to update the values else Insert the list into the Table.
With the list, I can insert the list of values in the table.
How to check and update the list in sql.
My Query :
WITH pq AS
(
SELECT A.[ProductId] ,A.[Quantity],A.[OrderId],D.[ProductName],E.[SpecialPrice],E.[SpecialPrice]*A.[Quantity] AS SPrice FROM [Table1] A
LEFT JOIN [Table2] B ON A.[OrderId] = B.[OrderId] INNER JOIN [Table3] D
ON A.[ProductId] = D.[ProductId] INNER JOIN [Table4] E
ON A.[ProductId] = E.[ProductId] WHERE B.[CustomerId] = 1
AND A.[OrderId] = 77
)
IF (EXISTS(SELECT [ProductId] FROM [Table5] WHERE [ProductId] = A.[ProductId]))
BEGIN
UPDATE [Table5]
SET [Quantity] = A.[Quantity]
WHERE B.[CustomerId] = 1 AND [ProductId] = A.[ProductId]
END
ELSE
BEGIN
INSERT INTO [Table5]
([ProductId],[ProductName],[Quantity],[Price],[TotalAmount])
SELECT
[ProductId],[ProductName],[Quantity],[SpecialPrice],SPrice
FROM pq;
END
Any suggestions will be greatly helpful.
EDIT : SELECT QUERY RESULT
ProductId Quantity
65 2
64 1
Assuming you're on SQL Server 2008 or above, the MERGE statement will solve your problem:
MERGE Table5 TRG
USING (
SELECT
A.ProductId,
A.Quantity,
A.OrderId,
D.ProductName,
E.SpecialPrice,
(E.SpecialPrice * A.Quantity) SPrice
FROM Table1 A
LEFT JOIN Table2 B ON A.OrderId = B.OrderId
INNER JOIN Table3 D ON A.ProductId = D.ProductId
INNER JOIN Table4 E ON A.ProductId = E.ProductId
WHERE
B.CustomerId = 1
AND A.OrderId = 77
) SRC
ON TRG.ProductID = SRC.ProductID
WHEN MATCHED THEN
UPDATE SET TRG.Quantity = SRC.Quantity
WHEN NOT MATCHED BY TARGET THEN
INSERT (
ProductId
, ProductName
, Quantity
, Price
, TotalAmount
)
VALUES (
SRC.ProductId
, SRC.ProductName
, SRC.Quantity
, SRC.SpecialPrice
, SRC.SPrice)
;
You can move the SELECT query out to a CTE for legibility like you did in your example.

Multiple COUNT(*) with join

I have to COUNT some rows from multiple tables. Before I can do multiple COUNT I will have to subselect. The problem here is that I need to JOIN some values in order to get the right result.
SELECT
sponsor.Name As SponsorName,
COUNT(participants.[Table]) AS ParticipantCount,
( SELECT
COUNT(guestcards.[Table])
FROM
guestcards
WHERE
guestcards.EventID = #EventID
AND
guestcards.[Table] = #Table
AND
guestcards.SponsorID = participants.SponsorID
-- Here lies the problem.
-- I will need to check up on another value to ensure I get the right rows, but participants.SponsorID is not here because of no join :-(
) AS GuestParticipantCount
FROM
participants
LEFT JOIN
sponsor
ON
sponsor.ID = participants.SponsorID
WHERE
participants.EventID = #EventID
AND
participants.[Table] = #Table
GROUP BY
sponsor.Name
Guestcards table holds: sponsorid, eventid, tablename
Participantstable holds: sponsorid, eventid, tablename
Sponsor table holds: id, name
I need to count how many "Participants" there are and how many "Guestcards" that in a particulary event. These participants have a table (where they should sit) and so does the guestcards. I need to check up on if its the same "table" where they sit.
So I need to count how many are sitting at table "A1" or table "A2" etc.
The result I am after is like:
"Sponsor Name has 5 participants and 3 guestcards. They sit on A1"
I hope I made my self clear
Here's exact equivalent of you query (grouping on sponsor.Name):
SELECT sponsor.name,
COALESCE(SUM(participantCount), 0),
COALESCE(SUM(guestcardsCount), 0)
FROM (
SELECT sponsorId, COUNT(*) AS participantCount
FROM participants
WHERE eventId = #eventId
AND [table] = #table
GROUP BY
sponsorId
) p
FULL JOIN
(
SELECT sponsorId, COUNT(*) AS guestcardsCount
FROM guestdcards
WHERE eventId = #eventId
AND [table] = #table
GROUP BY
sponsorId
) g
ON g.sponsorId = p.sponsorId
FULL JOIN
sponsor s
ON s.id = COALESCE(p.sponsorId, g.sponsorId)
GROUP BY
s.sponsorName
However, I believe you want something more simple:
SELECT sponsorName, participantCount, guestcardsCount
FROM sponsor s
CROSS APLLY
(
SELECT COUNT(*) AS participantCount
FROM participants
WHERE sponsorId = s.id
AND eventId = #eventId
AND [table] = #table
) p
CROSS APLLY
(
SELECT COUNT(*) AS guestcardsCount
FROM guestdcards
WHERE sponsorId = s.id
AND eventId = #eventId
AND [table] = #table
) g
Update:
SELECT sponsor.name,
COALESCE(participantCount, 0),
COALESCE(guestcardsCount, 0)
FROM (
SELECT sponsorId, COUNT(*) AS participantCount
FROM participants
WHERE eventId = #eventId
AND [table] = #table
GROUP BY
sponsorId
) p
FULL JOIN
(
SELECT sponsorId, COUNT(*) AS guestcardsCount
FROM guestdcards
WHERE eventId = #eventId
AND [table] = #table
GROUP BY
sponsorId
) g
ON g.sponsorId = p.sponsorId
JOIN sponsor s
ON s.id = COALESCE(p.sponsorId, g.sponsorId)

Get the most value from another column

I want to get data historical and the production. My stored procedure is as follows:
ALTER PROCEDURE [dbo].[pCaRptACInactivas](
#CodAsesor VARCHAR(15),
#CodOficina VARCHAR(4))
AS
SET NOCOUNT ON
DECLARE #CodArbolConta VARCHAR(25)
IF #CodOficina = '%'
SET #CodArbolConta = '%'
ELSE
SELECT #CodArbolConta = CodArbolConta + '%' FROM tClOficinas WHERE CodOficina LIKE #CodOficina
SELECT
tabACInactivas.CodOficina,
tabACInactivas.NomOficina,
tabACInactivas.NomAsesor,
MAX(tabACInactivas.CodPrestamo) CodPrestamo,
tabACInactivas.CodAsociacion,
tabACInactivas.NombreAsociacion,
MAX(tabACInactivas.Ciclo) AS Ciclo,
COUNT(DISTINCT tabACInactivas.CodUsuario) AS CantSocias,
MAX(tabACInactivas.FechaEstado) AS FechaCancelacion--,
FROM ( SELECT tClOficinas.CodOficina, tClOficinas.NomOficina, tCaClAsesores.CodAsesor, tCaClAsesores.NomAsesor, tCaPrestamos.CodPrestamo, tCaAsociacion.CodAsociacion, tCaAsociacion.NombreAsociacion, tCaPrestamos.Ciclo, tCaPrCliente.CodUsuario, tCaPrestamos.FechaEstado, tClParametros.FechaProceso FROM tCaPrestamos WITH(NOLOCK) INNER JOIN tCaProducto WITH(NOLOCK) ON tCaProducto.CodProducto = tCaPrestamos.CodProducto INNER JOIN tClOficinas WITH(NOLOCK) ON tClOficinas.CodOficina = tCaPrestamos.CodOficina INNER JOIN tCaAsociacion WITH(NOLOCK) ON tCaAsociacion.CodAsociacion = tCaPrestamos.CodAsociacion INNER JOIN tCaPrCliente WITH(NOLOCK) ON tCaPrCliente.CodPrestamo = tCaPrestamos.CodPrestamo INNER JOIN tClParametros WITH(NOLOCK) ON tClParametros.CodOficina = tClOficinas.CodOficina INNER JOIN tCaClAsesores ON tCaClAsesores.CodAsesor = tCaAsociacion.CodAsesor WHERE tCaPrestamos.Estado = 'CANCELADO' AND DATEDIFF(DAY, tCaPrestamos.FechaEstado, tClParametros.FechaProceso) > 30 AND NOT EXISTS(SELECT 1
FROM tCaPrestamos Pr
INNER JOIN tCaPrCliente PrCl ON PrCl.CodPrestamo = Pr.CodPrestamo
WHERE Pr.Estado NOT IN ('TRAMITE', 'APROBADO')
AND Pr.FechaDesembolso >= tCaPrestamos.FechaEstado
AND Pr.CodAsociacion = tCaPrestamos.CodAsociacion
) AND tCaProducto.Tecnologia = 3 AND tCaPrestamos.CodAsesor LIKE #CodAsesor AND tCaPrestamos.CodOficina IN (SELECT CodOficina FROM tClOficinas WHERE CodArbolConta LIKE #CodArbolConta)
UNION ALL
SELECT tClOficinas.CodOficina, tClOficinas.NomOficina, tCaClAsesores.CodAsesor, tCaClAsesores.NomAsesor, tCaHPrestamos.CodPrestamo, tCaAsociacion.CodAsociacion, tCaAsociacion.NombreAsociacion, tCaHPrestamos.Ciclo, tCaHPrCliente.CodUsuario, tCaHPrestamos.FechaEstado, tClParametros.FechaProceso FROM tCaHPrestamos WITH(NOLOCK) INNER JOIN tCaProducto WITH(NOLOCK) ON tCaProducto.CodProducto = tCaHPrestamos.CodProducto INNER JOIN tClOficinas WITH(NOLOCK) ON tClOficinas.CodOficina = tCaHPrestamos.CodOficina INNER JOIN tCaAsociacion WITH(NOLOCK) ON tCaAsociacion.CodAsociacion = tCaHPrestamos.CodAsociacion INNER JOIN tCaHPrCliente WITH(NOLOCK) ON tCaHPrCliente.CodPrestamo = tCaHPrestamos.CodPrestamo INNER JOIN tClParametros WITH(NOLOCK) ON tClParametros.CodOficina = tClOficinas.CodOficina INNER JOIN tCaClAsesores ON tCaClAsesores.CodAsesor = tCaAsociacion.CodAsesor WHERE tCaHPrestamos.Estado = 'CANCELADO' AND DATEDIFF(DAY, tCaHPrestamos.FechaEstado, tClParametros.FechaProceso) > 30 AND NOT EXISTS(SELECT 1
FROM tCaHPrestamos Pr
INNER JOIN tCaHPrCliente PrCl ON PrCl.CodPrestamo = Pr.CodPrestamo
WHERE Pr.Estado NOT IN ('TRAMITE', 'APROBADO')
AND Pr.FechaDesembolso >= tCaHPrestamos.FechaEstado
AND Pr.CodAsociacion = tCaHPrestamos.CodAsociacion
) AND tCaProducto.Tecnologia = 3 AND tCaHPrestamos.CodAsesor LIKE #CodAsesor AND tCaHPrestamos.CodOficina IN (SELECT CodOficina FROM tClOficinas WHERE CodArbolConta LIKE #CodArbolConta)
)tabACInactivas
GROUP BY tabACInactivas.CodAsociacion, tabACInactivas.NombreAsociacion, tabACInactivas.NomOficina, tabACInactivas.CodOficina, tabACInactivas.NomAsesor
I want the CantSocias column takes the most value of the Ciclo column, but not working
That stored procedure that you have posted up is way too large and blocky to even try to interpret and understand. So I will go off of your last sentence:
I want the CantSocias column takes the most value of the Ciclo column,
but not working
Basically if you want to set a specific column to that, you can do something like this:
update YourTable
set CantSocias =
(
select max(Ciclo)
from YourOtherTable
)
-- here is where you can put a conditional WHERE clause
You may need to create a sub query to get the most value of Ciclo and join back to your query.
An example of what I mean is here:
create table #Product
(
ID int,
ProductName varchar(20)
)
insert into #Product(ID, ProductName)
select 1,'ProductOne'
union
select 2,'ProductTwo'
create table #ProductSale
(
ProductID int,
Number int,
SalesRegion varchar(20)
)
insert into #ProductSale(ProductID,Number,SalesRegion)
select 1,1500,'North'
union
select 1, 1200, 'South'
union
select 2,2500,'North'
union
select 2, 3200, 'South'
--select product sales region with the most sales
select * from #Product p
select ProductId, Max(Number) as Bestsale from #ProductSale ps group by ProductID
--combining
select
p.ID,
p.ProductName,
tp.Bestsale,
ps.SalesRegion
from
#Product p
inner join
(select ProductId, Max(Number) as Bestsale from #ProductSale ps group by ProductID) as tp on p.ID = tp.ProductID
inner join
#ProductSale ps on p.ID = ps.ProductID and tp.Bestsale = ps.Number

Resources