Related
I want those Id whose Orgorder never equal to 1.
CREATE TABLE [dbo].[TEST](
[ORGORDER] [int] NULL,
[Id] [int] NOT NULL,
[ORGTYPE] [varchar](30) NULL,
ORGID INT NULL,
[LEAD] [decimal](19, 2) NULL
) ON [PRIMARY]
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE] ,ORGID, [LEAD]) VALUES (1, 100, N'ABC',1, NULL)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 100, N'ABC',2, 0)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 100, N'ACD',1, NULL)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (0, 101, N'ABC',0, 0)
GO
INSERT [dbo].[TEST] ([ORGORDER], [Id], [ORGTYPE],ORGID, [LEAD]) VALUES (2, 101, N'ABC',4, NULL)
GO
I am using exists but getting my result.
Expected result is -
ID
101
You can do this with one pass of the data, and order all ORGORDER = 1 first, then if it's the first row and it has the ORGORDER value you want to exclude, you can just ignore it.
;WITH x AS
(
SELECT Id, rn = ROW_NUMBER() OVER
(PARTITION BY Id ORDER BY CASE WHEN ORGORDER = 1 THEN 1 ELSE 2 END)
FROM dbo.TEST
)
SELECT Id FROM x WHERE rn = 1 AND ORGORDER <> 1;
Example db<>fiddle
Use a subquery in a NOT EXISTS clause, linking the subquery table to the outer query table by ID:
SELECT DISTINCT T1.ID
FROM dbo.TEST AS T1
WHERE NOT EXISTS (
SELECT *
FROM dbo.TEST AS T2
WHERE T1.ID = T2.ID
AND T2.ORGORDER = 1
)
db<>fiddle
An option would be using an aggregation with a suitable HAVING clause such as
SELECT [Id]
FROM [dbo].[TEST]
GROUP BY [Id]
HAVING SUM(CASE WHEN [ORGORDER] = 1 THEN 1 ELSE 0 END) = 0
where if there's at least one value equals to 1 for the concerned column([ORGORDER]), then that [Id] column won't be listed as result.
Demo
A table looks like this :
CREATE TABLE [dbo].[HistDT](
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL,
) ON [PRIMARY]
Example data set:
ID | StartDtSK | StartDt | Status |
1 20190520 20-05-2019 12:00:13 10
1 20190520 20-05-2019 10:00:00 5
1 20190414 14-04-2019 13:23:00 2
2 20190312 12-03-2019 10:03:00 10
2 20190308 08-03-2019 18:03:00 1
etc..
I need a query which will display the number of days spent in each status. That would be easy if the table i inherited had an end date. I would then calculate the datediff and pivot for column status values.
Maybe i should create a new table using ssis where i will add an EndDt column which will be the StartDt of the latest added Status.
But is there any way to do this without creating another table?
SQL Server 2008
This is not very pretty, and I haven't tested it for all use cases. I hope you can use it or find inspiration. I'm sure there is a better way :)
declare #table2 table (
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL
)
insert into #table2
values
(1 , '20190520','2019-05-20 12:00:13','10'),
(1 , '20190520','2019-05-20 10:00:00','5'),
(1 , '20190414','2019-04-14 13:23:00','2'),
(2, '20190312', '2019-03-12 10:03:00', '10'),
(2 , '20190308', '2019-03-08 18:03:00', '1')
select *,DATEDIFF(dd,startdt,enddate) as TotalDAys from (
select x.ID,StartDtSK,Startdt,[Status],Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt) as rn from #table2
) x
cross apply ( select * from (select id,StartDt as Enddate,ROW_NUMBER() over(partition by id order by startdt) as rn2 from #table2 b
)f where (rn +1 = f.rn2 ) and x.id = f.id ) d
union all
select ID,StartDtSK,startdt,[Status],'9999-12-31' as Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt desc) as rn from #table2
)X where rn=1
)y
order by id,startdt
SQL Server 2008 without cross apply
This might be a bit more pretty :)
select *,DATEDIFF(dd,startdt,enddate) as TotalDAys from (
select x.ID,StartDtSK,Startdt,[Status],case when Enddate is null then '9999-12-31' else Enddate end as Enddate from (
select *,ROW_NUMBER() over(partition by id order by startdt) as rn from #table2
) x
left join (
select * from (select id,StartDt as Enddate,ROW_NUMBER() over(partition by id order by startdt) as rn2 from #table2 b
)f ) d on (rn +1 = d.rn2 ) and x.id = d.id
)y
SQL Server 2012 and above:
Is this what you want?
declare #table2 table (
[ID] [bigint] NULL,
[StartDtSK] [varchar](8) NULL,
[StartDt] [datetime] NULL,
[status] [nvarchar](30) NULL
)
insert into #table2
values
(1 , '20190520','2019-05-20 12:00:13','10'),
(1 , '20190520','2019-05-20 10:00:00','5'),
(1 , '20190414','2019-04-14 13:23:00','2')
select *,Datediff(dd,Startdt,Enddate) as TotalDays from (
select *,LAG(StartDt,1,'9999-12-31') over(partition by ID order by StartDT desc) as EndDate from #table2
)x
Insert a rule that handles current status (9999-12-31) date
Maybe LEAD function is usefull for your question.
Like this
IsNull(DateAdd(SECOND,-1,Cast(LEAD ([StartDt],1) OVER (PARTITION BY [status] ORDER BY [StartDt]) AS DATETIME)),getdate()) AS EndDate
I have two tables (Table1 & Table2). One including a date (tDate) column and an ID (tTillNo) column that I would like to group by. And another with values (pValue) that I would like to sum for each date and ID.
The tables can be joined using the 'tName' and 'pName' columns from each table, however the pName column may have duplicates, which I would like to include in the sum.
For the 3 sub queries I also need to include the where clauses using the 'pCode' column.
And I would like to return the columns shown here
Using the below code however returns the sub queries with incorrect totals as I am using 'MAX(a.tName)' to prevent the grouping of this field. Could anyone suggest another way of preventing this or an alternative way of going about this query?
SELECT
DATENAME(Month,a.tDate) as 'Month Name', DAY(a.tDate) as 'Day',
MONTH(a.tDate) as 'Month', YEAR(a.tDate) as 'Year', a.tTillNo,
BankedCash=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0)
FROM Table2 b
where MAX(a.tName)=b.pName AND pCode = 'CSH'
or pCode = 'CHQ'),
CardTransactions=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0)
FROM Table2 b
where MAX(a.tName)=b.pName AND b.pCode = 'CRD'),
BankingTotal=(SELECT ISNULL(CAST(SUM(b.pValue) as numeric(12,2)),0)
FROM Table2 b
where MAX(a.tName)=b.pName AND b.pCode = 'CSH' or
b.pCode = 'CHQ' or b.pCode = 'CRD')
FROM Table1 a
group by YEAR(a.tDate), MONTH (a.tDate), DATENAME(Month,a.tDate),
DAY(a.tDate), a.tTillNo
order by YEAR(a.tDate), MONTH (a.tDate), DATENAME(Month,a.tDate)
Any suggestions or article referrals would be highly appreciated. Many thanks in advance.
CREATE TABLE [dbo].[Table1](
[UniqueID] [int] IDENTITY(1,1) NOT NULL,
[tTillNo] [varchar](4) NULL,
[tName] [varchar](20) NULL,
[tDate] [datetime] NULL)
INSERT INTO Table1 (tTillNo, tName, tDate)
VALUES ('0101', '01010000001', '2018-10-30 00:00:00.000'),
('0101', '01010000002', '2018-10-30 00:00:00.000'),
('0102', '01020000001', '2018-10-30 00:00:00.000'),
('0102', '01020000002', '2018-10-30 00:00:00.000')
CREATE TABLE [dbo].[Table2](
[UniqueID] [int] IDENTITY(1,1) NOT NULL,
[pName] [varchar](20) NULL,
[pCode] [varchar](10) NULL,
[pValue] [decimal](22, 7) NULL)
INSERT INTO Table2 (pName, pCode, pValue)
VALUES ('01010000001', 'CRD', '100.0000000'),
('01010000002', 'CSH', '100.0000000'),
('01020000001', 'CHQ', '100.0000000'),
('01020000002', 'CSH', '100.0000000'),
('01020000002', 'CRD', '100.0000000'),
('01010000001', 'CSH', '100.0000000')
I think you can solve this all with a join.
select DATENAME(Month,a.tDate) as 'Month Name'
, DAY(a.tDate) as 'Day'
, MONTH(a.tDate) as 'Month'
, YEAR(a.tDate) as 'Year'
, a.tTillNo
, BankedCash=SUM(case when pCode in( 'CSH','CHQ') then pvalue else 0 end)
, [Card] = SUM(case when pCode in( 'CRD') then pvalue else 0 end)
,Total = SUM(pvalue)
from TableA a
join TableB b on a.tName=b.pName
group by YEAR(a.tDate)
, MONTH (a.tDate)
, DATENAME(Month,a.tDate)
, DAY(a.tDate)
, a.tTillNo
I have a data as below:
I need to update Matching_id and Matching_Type by using column id, region, company, dept, subdept and amountsepend. The logic is:
Sum AmountSepend by Region, Company, Dept and SubDept. If the sum amount is 0 then Matching_Type is 'Match' and Matching_id is the combination of the id for the matched record else 'Not Match' and Matching_id is the id. **SUM means the total sum of all records for same criteria regardless the AmountSepend is positive or negative.
Another important criteria is if the transaction is single record, meaning the total count by grouping by Region, Company, Dept and SubDept is 1 then Matching type is Not Match and Matching_UID is id regardless the AmountSepend is 0 or positive/negative value. Example id 8.
Below is the output:
Here the table and data script
CREATE TABLE [dbo].[StackoverflowQuest](
[id] [int] NOT NULL,
[Region] [varchar](50) NULL,
[Company] [varchar](50) NULL,
[Dept] [varchar](50) NULL,
[SubDept] [varchar](50) NULL,
[AmountSepend] [float] NULL,
[Matching_id] [varchar](100) NULL,
[Matching_Type] [varchar](100) NULL
) ON [PRIMARY]
How could I achieved such result ? Any help/hint would be appreciate
CREATE TABLE #Table(Id INT,Region VARCHAR(100),Company INT,Dept INT,SubDept
INT,AmtSpend INT,MatchingId VARCHAR(100),MatchingType VARCHAR(100))
INSERT INTO #Table(Id ,Region ,Company , Dept ,SubDept ,AmtSpend )
SELECT 1,'NAM',12378,1,NULL,900 UNION ALL
SELECT 2,'NAM',12378,1,NULL,-900 UNION ALL
SELECT 3,'NAM',12370,1,23,1000 UNION ALL
SELECT 4,'ASA',1234,9,12,5000 UNION ALL
SELECT 5,'NAM',12370,1,23,-1000 UNION ALL
SELECT 6,'ASA',1234,9,12,800 UNION ALL
SELECT 7,'ASA',1234,9,12,-600 UNION ALL
SELECT 8,'ASA',12311,6,NULL,200
UPDATE #Table SET MatchingId = MatchIds,MatchingType = 'Match'
FROM
(
SELECT T2.Company,STUFF( ( SELECT ',' + CAST(T3.Id AS VARCHAR) FROM #Table
T3 WHERE T2.Company = T3.Company FOR XML PATH('')),1,1,'') MatchIds
FROM #Table T2
JOIN
(
SELECT T1.Company Company,SUM(T1.AmtSpend) Total
FROM #Table T1
GROUP BY T1.Company
HAVING SUM(T1.AmtSpend) = 0
)A ON A.Company = T2.Company
GROUP BY T2.Company
) A
WHERE A.Company = #Table.Company
UPDATE #Table SET MatchingId = CAST(Id AS VARCHAR),MatchingType = 'Not
Match' WHERE ISNULL(MatchingId,'') = ''
SELECT * FROM #Table
I don't know how to explain my problem in the title, so I'll explain it better here...
I have two tables
CREATE TABLE [dbo].[Ventas]
(
[IdVenta] [int] IDENTITY(1,1) NOT NULL,
[FechaVenta] [date] NULL,
[HoraVenta] [varchar](10) NULL,
[Subtotal] [money] NULL,
[Iva] [money] NULL,
[Total] [money] NULL,
[Saldo] [money] NULL,
[Abono] [money] NULL,
[FormaDePago] [varchar](50) NULL,
[Plazos] [int] NULL,
[Estado] [varchar](50) NULL,
)
CREATE TABLE [dbo].[Plazos]
(
[IdPlazo] [int] IDENTITY(1,1) NOT NULL,
[IdVenta] [int] NULL,
[NumeroPlazo] [int] NULL,
[FechaVencimiento] [date] NULL,
[FechaCorte] [date] NULL,
[FechaPenalizacion] [date] NULL,
[FechaLiquidacion] [date] NULL,
[Total] [money] NULL,
[Cargo] [money] NULL,
[Abono] [money] NULL,
[Estado] [varchar](50) NULL,
)
now to add some data
INSERT [dbo].[Ventas] ([IdVenta], [FechaVenta], [HoraVenta], [Subtotal], [Iva], [Total], [Saldo], [Abono], [FormaDePago], [Plazos], [Estado]) VALUES (182, CAST(0x54360B00 AS Date), N'11:20', 500.0000, 55.0000, 555.0000, 333.0000, 222.0000, N'A Credito', 5, N'Pendiente De Pago')
INSERT [dbo].[Ventas] ([IdVenta], [FechaVenta], [HoraVenta], [Subtotal], [Iva], [Total], [Saldo], [Abono], [FormaDePago], [Plazos], [Estado]) VALUES (183, CAST(0x54360B00 AS Date), N'12:29', 575.0000, 63.2500, 638.2500, 638.2500, 0.0000, N'Una Sola Exhibicion', 1, N'Pendiente De Pago')
INSERT [dbo].[Plazos] ([IdPlazo], [IdVenta], [NumeroPlazo], [FechaVencimiento], [FechaCorte], [FechaPenalizacion], [FechaLiquidacion], [Total], [Cargo], [Abono], [Estado]) VALUES (93, 182, 1, CAST(0x54360B00 AS Date), CAST(0x57360B00 AS Date), CAST(0x5C360B00 AS Date), CAST(0x54360B00 AS Date), 111.0000, 0.0000, 111.0000, N'Liquidado')
INSERT [dbo].[Plazos] ([IdPlazo], [IdVenta], [NumeroPlazo], [FechaVencimiento], [FechaCorte], [FechaPenalizacion], [FechaLiquidacion], [Total], [Cargo], [Abono], [Estado]) VALUES (94, 182, 2, CAST(0x73360B00 AS Date), CAST(0x75360B00 AS Date), CAST(0x7A360B00 AS Date), CAST(0x54360B00 AS Date), 111.0000, 0.0000, 111.0000, N'Liquidado')
INSERT [dbo].[Plazos] ([IdPlazo], [IdVenta], [NumeroPlazo], [FechaVencimiento], [FechaCorte], [FechaPenalizacion], [FechaLiquidacion], [Total], [Cargo], [Abono], [Estado]) VALUES (95, 182, 3, CAST(0x91360B00 AS Date), CAST(0x94360B00 AS Date), CAST(0x99360B00 AS Date), NULL, 111.0000, 111.0000, 0.0000, N'Pendiente')
INSERT [dbo].[Plazos] ([IdPlazo], [IdVenta], [NumeroPlazo], [FechaVencimiento], [FechaCorte], [FechaPenalizacion], [FechaLiquidacion], [Total], [Cargo], [Abono], [Estado]) VALUES (96, 183, 1, CAST(0x54360B00 AS Date), CAST(0x57360B00 AS Date), CAST(0x5C360B00 AS Date), NULL, 639.0000, 639.0000, 0.0000, N'Pendiente')
Foreign Key On Ventas.IdVenta = Plazos.IdVenta
Ok, Here's the deal...
I need to use a query that brings data from all sales (Ventas), which only it supposed to be 2 rows...
However, I need data from Plazos, but I only need data from Plazos
What I need is to display data from plazos on the same row as Ventas, but only data from the most recent Plazo...
you may notice that for example, in Plazos there is a column called NumeroPlazo which increases on the same IdVenta... what I need in this example is to display:
Ventas IdVenta 182 with data from Plazos IdPlazo 95 (since from Plazos, IdPlazo 95 has the highest number on the column Numero Plazos...
and of course IdVenta 183, but since it only has one Plazo, it will display data from that plazo...
At the moment I had this query...
SELECT Ventas.*, Plazos.*,
FROM Ventas INNER JOIN Plazos ON Plazos.IdVenta = Ventas.IdVenta
WHERE Ventas.Estado = 'Pendiente De Pago'
ORDER BY Ventas.FechaVenta DESC, Ventas.HoraVenta DESC
but it returns 4 rows (3 rows for Venta where IdVenta = 182, and one where IdVenta = 183)
What I want is only 2 rows...
Then I tried this query that worked... but only for one row
SELECT Ventas.*, Plazos.*,
FROM Ventas INNER JOIN Plazos ON Plazos.IdVenta = Ventas.IdVenta
WHERE Ventas.Estado = 'Pendiente De Pago'
AND Plazos.NumeroPlazo = (SELECT MAX(Plazos.NumeroPlazo) FROM Plazos WHERE Plazos.IdVenta = 182)
ORDER BY Ventas.FechaVenta DESC, Ventas.HoraVenta DESC
Obviously it only works for one sale since I specify Plazos.IdVenta = 182...
My question here is... how can I use the latter query to get the data I want for each sale...
I hope yuo can help me...
If you need me to be more specific, please let me know.
Thanks in advance
You can use CROSS APPLY which allows you to run a subquery per-each-row of the preceding tables in the FROM list.
SELECT Ventas.*, Plazos.*
FROM Ventas
cross apply (
select TOP(1) *
from Plazos
WhERE Plazos.IdVenta = Ventas.IdVenta
ORDER BY [NumeroPlazo] DESC) Plazos
WHERE Ventas.Estado = 'Pendiente De Pago'
ORDER BY Ventas.FechaVenta DESC, Ventas.HoraVenta DESC
Doing it via Row_Number() is probably faster, but here the subquery will require you to alias all the columns at the inner level, which is probably not a bad idea anyway.
SELECT *
FROM
(
SELECT
v.[IdVenta], v.[FechaVenta], v.[HoraVenta], v.[Subtotal], v.[Iva], v.[Total], v.[Saldo], v.[Abono], v.[FormaDePago], v.[Plazos], v.[Estado],
p.[IdPlazo], p.[NumeroPlazo], p.[FechaVencimiento], p.[FechaCorte], p.[FechaPenalizacion], p.[FechaLiquidacion], p.[Total] plazostotal, p.[Cargo], p.[Abono] plazasabono, p.[Estado] plazosestado,
RowN = ROW_NUMBER() over (partition by v.[IdVenta] order by p.[NumeroPlazo] desc)
FROM Ventas v
JOIN Plazos p ON p.IdVenta = v.IdVenta
WHERE v.Estado = 'Pendiente De Pago'
) X
WHERE RowN = 1
ORDER BY FechaVenta DESC, HoraVenta DESC
It is simple. In your second question replace 182 on Ventas.IdVenta
SELECT Ventas.*, Plazos.*
FROM Ventas INNER JOIN Plazos ON Plazos.IdVenta = Ventas.IdVenta
WHERE Ventas.Estado = 'Pendiente De Pago'
AND Plazos.NumeroPlazo = (SELECT MAX(Plazos.NumeroPlazo) FROM Plazos WHERE Plazos.IdVenta = Ventas.IdVenta)
ORDER BY Ventas.FechaVenta DESC, Ventas.HoraVenta DESC