tylern
tylern

Reputation: 64

SQL Server : update boolean column based on conditions from 2 other columns

I need to set all rows to 1 (true) in column PrimaryInvoiceFile when my InvoiceFileId only has one InvoiceId.

However, if InvoiceId has multiple has multiple InvoiceFileId, I need to set all of the PrimaryInvoiceFile rows to 0 (false) except for the most recent InvoiceFileId added based on the date added.

For example it should look like this:

|CreatedDate|InvoiceId|InvoiceFileId|PrimaryInvoiceFile|
+-----------+---------+-------------+------------------+
|2019-01-16 | 1       | 1           | 1                |
|2019-01-17 | 2       | 2           | 1                |
|2019-01-18 | 3       | 3           | 0                |
|2019-01-19 | 3       | 4           | 0                |
|2019-01-20 | 3       | 5           | 1                |
|2019-01-21 | 4       | 6           | 1                |

I just added the PrimaryInvoiceFile column migration and set the default value to 0.

Any help with this would be greatly appreciated! I have been racking my head with this trying to get my update statements to perform this update.

Upvotes: 2

Views: 2712

Answers (3)

Peeyush
Peeyush

Reputation: 726

If the default PrimaryInvoiceFile is set to 0, you need to update the PrimaryInvoiceFile of the maximum CreatedDate grouped by InvoiceId.

UPDATE inv1 
SET inv1.PrimaryInvoiceFile = 1
FROM invoices inv1 JOIN 
    (SELECT max(CreatedDate) as maxDate, InvoiceId 
     FROM invoices 
     GROUP BY InvoiceId ) as inv2  
WHERE inv1.CreatedDate=inv2.maxDate and inv1.InvoiceId= inv2.InvoiceId 

Upvotes: 0

Avi
Avi

Reputation: 1845

You can make use of rownumber while doing your update to achieve your desired results. Also, order by descending so that you get the most recent date.

Lets create a table keeping PrimaryInvoiceFile as null and then updating later.

select '2019-01-16' as CreatedDate, 1 as invoiceID,         1 as Invoicefield, null 
as PrimaryInvoiceFile 
into #temp 
union all 
select '2019-01-17' as CreatedDate, 2 as invoiceID,         2 as Invoicefield, null 
as Primaryinvoicefile union all 
select '2019-01-18' as CreatedDate, 3 as invoiceID,         3 as Invoicefield, null 
as Primaryinvoicefile union all 
select '2019-01-19' as CreatedDate, 3 as invoiceID,         4 as Invoicefield, null 
as Primaryinvoicefile union all 
select '2019-01-20' as CreatedDate, 3 as invoiceID,         5 as Invoicefield, null 
 as Primaryinvoicefile union all 
 select '2019-01-21' as CreatedDate, 4 as invoiceID,         6 as Invoicefield, null 
 as Primaryinvoicefile

update t 
set Primaryinvoicefile = tst.Rownum 
from #temp t 
join  
(Select  invoiceID, Invoicefield,CreatedDate, 
case when ROW_NUMBER() over (partition by invoiceID order by createddate desc) = 1 
then 1 else 0 end as Rownum   from #temp) tst 
on  tst.CreatedDate = t.CreatedDate 
      and tst.invoiceID = t.invoiceID 
      and tst.Invoicefield =  t.Invoicefield 

Case statement would make sure that you are value as 1 for only the rows where you have 1 row for invoice ID or for the most recent data. 

select * from #temp 

Output:

 CreatedDate    invoiceID   Invoicefield    PrimaryInvoiceFile
 2019-01-16        1          1                    1
 2019-01-17        2          2                    1
 2019-01-18        3          3                    0
 2019-01-19        3          4                    0
 2019-01-20        3          5                    1
 2019-01-21        4          6                    1

Upvotes: 4

Vitaly Borisov
Vitaly Borisov

Reputation: 1193

Please try this:

;WITH Data AS (
    SELECT t.CreatedDate,t.InvoiceId,t.InvoiceFieldId,t.PrimaryInvoiceFile
        ,COUNT(*)OVER(PARTITION BY t.InvoiceId) AS [cnt]
    FROM [YourTableName] t
)
UPDATE d SET d.PrimaryInvoiceFile = CASE WHEN d.cnt = 1 THEN 1 ELSE 0 END
FROM Data d
;

Query to play around:

DROP TABLE IF EXISTS #YourTableName;
CREATE TABLE #YourTableName(CreatedDate DATETIME2,InvoiceId INT, InvoiceFieldId INT,PrimaryInvoiceFile BIT);
INSERT INTO #YourTableName(CreatedDate,InvoiceId,InvoiceFieldId)VALUES
    ('2019-01-16',1,1),('2019-01-17',2,2),('2019-01-18',3,3),('2019-01-19',3,4),('2019-01-20',3,5),('2019-01-21',4,6)

;WITH Data AS (
    SELECT t.CreatedDate,t.InvoiceId,t.InvoiceFieldId,t.PrimaryInvoiceFile,COUNT(*)OVER(PARTITION BY t.InvoiceId) AS [cnt]
    FROM #YourTableName t
)
UPDATE d SET d.PrimaryInvoiceFile = CASE WHEN d.cnt = 1 THEN 1 ELSE 0 END
FROM Data d
;

SELECT t.CreatedDate,t.InvoiceId,t.InvoiceFieldId,t.PrimaryInvoiceFile
FROM #YourTableName t
;

DROP TABLE IF EXISTS #YourTableName;

Upvotes: 2

Related Questions