Insert nulls during bulk insert for Postgres - postgresql

I am trying to convert this sqlfiddle http://www.sqlfiddle.com/#!3/fbaff/14 from MSSQL Server to Postgres but cannot get the sample data script to insert null values. My end goal is this convert this query to work on the same data and structure, but in Postgres:
select a1.OrderNumber, a1.New as Step,
sum(datediff(second, a1.TimeEntered, isnull(a2.timeEntered,getdate()))) as [Total Time in Step (seconds)]
from AuditTrail a1
left join AuditTrail a2
on a1.New = a2.Old
and a1.OrderNumber = a2.OrderNumber
group by a1.OrderNumber, a1.New
order by a1.OrderNumber
I have tried various versions of "", '', NULL, and IS NULL.
create table AuditTrail(
Old varchar(50),
New varchar(50),
TimeEntered Timestamp,
OrderNumber varchar(50)
);
insert into "AuditTrail"
( **THIS SHOULD BE NULL**, 'Step 1' , '4/30/12 10:43 ','1C2014A'),
('Step 1', 'Step 2' , ' 5/2/12 10:17 ','1C2014A'),
('Step 2', 'Step 3' , ' 5/2/12 10:28 ','1C2014A'),
('Step 3', 'Step 4' , ' 5/2/12 11:14 ','1C2014A'),
('Step 4', 'Step 5' , ' 5/2/12 11:19 ','1C2014A'),
('Step 5', 'Step 9' , ' 5/3/12 11:23 ','1C2014A'),
(NULL , 'Step 1' , '5/18/12 15:49 ','1C2014B'),
('Step 1', 'Step 2' , ' 5/21/12 9:21 ','1C2014B'),
('Step 2', 'Step 3' , ' 5/21/12 9:34 ','1C2014B'),
('Step 3', 'Step 4' , ' 5/21/12 10:08','1C2014B'),
('Step 4', 'Step 5' , ' 5/21/12 10:09','1C2014B'),
('Step 5', 'Step 6' , ' 5/21/12 16:27','1C2014B'),
('Step 6', 'Step 9' , ' 5/21/12 18:07','1C2014B'),
(NULL , 'Step 1' , '6/12/12 10:28 ','1C2014C'),
('Step 1', 'Step 2' , ' 6/13/12 8:36 ','1C2014C'),
('Step 2', 'Step 3' , ' 6/13/12 9:05 ','1C2014C'),
('Step 3', 'Step 4' , ' 6/13/12 10:28 ','1C2014C'),
('Step 4', 'Step 6' , ' 6/13/12 10:50','1C2014C'),
('Step 6', 'Step 8' , ' 6/13/12 12:14','1C2014C'),
('Step 8', 'Step 4' , ' 6/13/12 15:13','1C2014C'),
('Step 4', 'Step 5' , ' 6/13/12 15:23','1C2014C'),
('Step 5', 'Step 8' , ' 6/13/12 15:30','1C2014C'),
('Step 8', 'Step 9' , ' 6/18/12 14:04','1C2014C')

try this:
insert into AuditTrail values
( NULL, 'Step 1' , '4/30/12 10:43 ','1C2014A'),
('Step 1', 'Step 2' , ' 5/2/12 10:17 ','1C2014A'),
('Step 2', 'Step 3' , ' 5/2/12 10:28 ','1C2014A'),
('Step 3', 'Step 4' , ' 5/2/12 11:14 ','1C2014A'),
('Step 4', 'Step 5' , ' 5/2/12 11:19 ','1C2014A'),
('Step 5', 'Step 9' , ' 5/3/12 11:23 ','1C2014A'),
(NULL , 'Step 1' , '5/18/12 15:49 ','1C2014B'),
('Step 1', 'Step 2' , ' 5/21/12 9:21 ','1C2014B'),
('Step 2', 'Step 3' , ' 5/21/12 9:34 ','1C2014B'),
('Step 3', 'Step 4' , ' 5/21/12 10:08','1C2014B'),
('Step 4', 'Step 5' , ' 5/21/12 10:09','1C2014B'),
('Step 5', 'Step 6' , ' 5/21/12 16:27','1C2014B'),
('Step 6', 'Step 9' , ' 5/21/12 18:07','1C2014B'),
(NULL , 'Step 1' , '6/12/12 10:28 ','1C2014C'),
('Step 1', 'Step 2' , ' 6/13/12 8:36 ','1C2014C'),
('Step 2', 'Step 3' , ' 6/13/12 9:05 ','1C2014C'),
('Step 3', 'Step 4' , ' 6/13/12 10:28 ','1C2014C'),
('Step 4', 'Step 6' , ' 6/13/12 10:50','1C2014C'),
('Step 6', 'Step 8' , ' 6/13/12 12:14','1C2014C'),
('Step 8', 'Step 4' , ' 6/13/12 15:13','1C2014C'),
('Step 4', 'Step 5' , ' 6/13/12 15:23','1C2014C'),
('Step 5', 'Step 8' , ' 6/13/12 15:30','1C2014C'),
('Step 8', 'Step 9' , ' 6/18/12 14:04','1C2014C');
I think you need the VALUES keyword.
Also the double-quotes around the table name probably causes a parse error.

Related

Pivot table with case statement

I have a table like so. I am trying to get it to pivot to be a singular record. The issue is that the transporter line number goes to like 231 for some records (bad public dataset). So my solution is to return the first transporter, 2-9 transporter, final transporter. However I am struggling to understand how to incorporate the max value to return into the query as I get the error of aggregate within an aggregate.
Select manifesttrackingnumber,
Min(Case TRANSPORTERLINENUMBER When 1 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'First Transporter',
Min(Case TRANSPORTERLINENUMBER When 2 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 2',
Min(Case TRANSPORTERLINENUMBER When 3 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 3',
Min(Case TRANSPORTERLINENUMBER When 4 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 4',
Min(Case TRANSPORTERLINENUMBER When 5 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 5',
Min(Case TRANSPORTERLINENUMBER When 6 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 6',
Min(Case TRANSPORTERLINENUMBER When 7 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 7',
Min(Case TRANSPORTERLINENUMBER When 8 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 8',
Min(Case TRANSPORTERLINENUMBER When 9 Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Transporter 9',
Max(Case TRANSPORTERLINENUMBER When max(transporterlinenumber) Then concat(trim(TRANSPORTERNAME),' (',trim(TRANSPORTEREPAID),')') End) 'Final Transporter'
From TRANSPORTER
Implemented a subquery to return the max number for each ID.

Looping updates - better way to do this?

I am stuck on this problem. I am thinking that I may need a looping update (if that exists), but maybe there is a better way?
I am working with claims drug prescription data, so essentially 5 columns
User, Drug, RxStartDate, DaySupply, and
'RxEndDate' = dateadd(dd, DaySupply-1, RxStartDate)
If the same user has 2 prescriptions that overlap (Rx1 EndDate >= Rx2 StartDate), then I need to sum the DaySupply together.
Once I sum the DaySupply, the RxEndDate will extend and I need to check again if there is overlap in the prescription.
Currently I have the following code that I have to run and re-run until I don't have anymore updates, but I know there must be a better way to do this...
UPDATE b
SET b.RxStartDate= a.RxStartDate
FROM RxClaims a
JOIN RxClaims b on a.User=b.User and a.Drug = b.Drug
WHERE b.RxStartDate<= a.RxEndDate
and a.RxStartDate< b.RxStartDate
SELECT User, Drug, RxStartDate, sum(DaySupply) as DaySupply,
'RxEndDate' = dateadd(dd, sum(DaySupply)-1, RxStartDate)
into RxClaims2
from RxClaims
group by User, Drug, RxStartDate
Thoughts anyone?
sample data:
User Drug RxStartDate DaySupply RxEndDate
Amy Humera 2/12/2017 7 2/18/2017
Amy Humera 2/28/2017 5 3/4/2017
Amy Humera 3/3/2017 5 3/7/2017
Amy Humera 3/8/2017 2 3/9/2017
Amy Humera 3/10/2017 7 3/16/2017
Amy Humera 3/17/2017 30 4/15/2017
Amy Humera 3/22/2017 2 3/23/2017
Amy Humera 3/24/2017 2 3/25/2017
Amy Humera 3/31/2017 3 4/2/2017
Amy Humera 4/7/2017 5 4/11/2017
Amy Humera 4/13/2017 30 5/12/2017
after 1st time running my current code
User Drug RxStartDate DaySupply RxEndDate
Amy Humera 2/12/2017 7 2/18/2017
Amy Humera 2/28/2017 10 3/9/2017
Amy Humera 3/8/2017 2 3/9/2017
Amy Humera 3/10/2017 7 3/16/2017
Amy Humera 3/17/2017 72 5/27/2017
after 2nd time running my current code
User Drug RxStartDate DaySupply RxEndDate
Amy Humera 2/12/2017 7 2/18/2017
Amy Humera 2/28/2017 12 3/11/2017
Amy Humera 3/10/2017 7 3/16/2017
Amy Humera 3/17/2017 72 5/27/2017
after 3rd time running my current code
User Drug RxStartDate DaySupply RxEndDate
Amy Humera 2/12/2017 7 2/18/2017
Amy Humera 2/28/2017 19 3/18/2017
Amy Humera 3/17/2017 72 5/27/2017
after 4th time running my current code
User Drug RxStartDate DaySupply RxEndDate
Amy Humera 2/12/2017 7 2/18/2017
Amy Humera 2/28/2017 91 5/29/2017
There is no more overlap…finished!
I think the solution can only be implemented by recursion, as there should be a loop that calculates the accumulated DaySupply and I see no way of doing that with any non-recursive lookups. You can do this with recursive CTE.
A possible implementation:
DECLARE #test TABLE (
[User] VARCHAR(100),
Drug VARCHAR(100),
RxStartDate DATE,
DaySupply INT,
RxEndDate DATE
)
INSERT #test
VALUES
('Amy', 'Humera', '2/12/2017', '7', '2/18/2017'),
('Amy', 'Humera', '2/28/2017', '5', '3/4/2017'),
('Amy', 'Humera', '3/3/2017', '5', '3/7/2017'),
('Amy', 'Humera', '3/8/2017', '2', '3/9/2017'),
('Amy', 'Humera', '3/10/2017', '7', '3/16/2017'),
('Amy', 'Humera', '3/17/2017', '30', '4/15/2017'),
('Amy', 'Humera', '3/22/2017', '2', '3/23/2017'),
('Amy', 'Humera', '3/24/2017', '2', '3/25/2017'),
('Amy', 'Humera', '3/31/2017', '3', '4/2/2017'),
('Amy', 'Humera', '4/7/2017', '5', '4/11/2017'),
('Amy', 'Humera', '4/13/2017', '30', '5/12/2017'),
('Amy', 'Other', '3/24/2017', '7', '3/30/2017'),
('Amy', 'Other', '3/31/2017', '3', '4/2/2017'),
('Amy', 'Other', '4/7/2017', '5', '4/11/2017'),
('Amy', 'Other', '4/13/2017', '30', '5/12/2017'),
('Joe', 'Humera', '3/24/2017', '8', '3/31/2017'),
('Joe', 'Humera', '3/31/2017', '3', '4/2/2017'),
('Joe', 'Humera', '4/12/2017', '5', '4/16/2017'),
('Joe', 'Humera', '4/23/2017', '30', '5/22/2017'),
('Joe', 'Other', '3/24/2017', '60', '5/23/2017'),
('Joe', 'Other', '3/31/2017', '3', '4/2/2017'),
('Joe', 'Other', '4/7/2017', '5', '4/11/2017'),
('Joe', 'Other', '4/13/2017', '30', '5/12/2017')
-- You can comment this out, it is just to show progress:
SELECT * FROM #test ORDER BY [User], Drug, RxStartDate
DECLARE #test_2 TABLE (
[User] VARCHAR(100),
Drug VARCHAR(100),
RxStartDate_base DATE,
DaySupplyCumulative INT
)
;WITH CTE_RxEndDateExtended as (
SELECT [User], Drug, RxStartDate, DaySupply, DaySupply as DaySupplyCumulative, RxStartDate as RxStartDate_base, RxStartDate as RxStartDateExtended, dateadd (dd, DaySupply, RxStartDate) as RxEndDateExtended
FROM #test
-- WHERE [User] = 'Amy' and Drug = 'Humera' and RxStartDate = '2/28/2017'
UNION ALL
SELECT t.[User], t.Drug, t.RxStartDate, t.DaySupply, c.DaySupplyCumulative + t.DaySupply as DaySupplyCumulative, c.RxStartDate_base, t.RxStartDate as RxStartDateExtended, dateadd (dd, t.DaySupply, c.RxEndDateExtended) as RxEndDateExtended
FROM CTE_RxEndDateExtended as c INNER JOIN #test as t
on c.[User] = t.[User] and c.Drug = t.Drug
and c.RxEndDateExtended >= t.RxStartDate and c.RxStartDateExtended < t.RxStartDate
)
INSERT #test_2
SELECT [User], Drug, RxStartDate_base, MAX (DaySupplyCumulative) as DaySupplyCumulative -- comment this out and use this for debugging: SELECT *
FROM CTE_RxEndDateExtended
GROUP BY [User], Drug, RxStartDate_base -- comment this out for debugging
OPTION (MAXRECURSION 0) -- comment this out and use this for debugging (to avoid infinite loops): OPTION (MAXRECURSION 1000)
-- You can comment this out, it is just to show progress:
SELECT * FROM #test_2
ORDER BY [User], Drug, RxStartDate_base -- comment this out and use this for debugging: ORDER BY [User], Drug, RxStartDate_base, RxStartDate, DaySupplyCumulative
SELECT base.*, dateadd (dd, base.DaySupplyCumulative - 1, base.RxStartDate_base) as RxEndDateCumulative
FROM #test_2 as base LEFT OUTER JOIN #test_2 as filter
on base.[User] = filter.[User] and base.Drug = filter.Drug
and base.RxStartDate_base > filter.RxStartDate_base
and dateadd (dd, base.DaySupplyCumulative, base.RxStartDate_base) <= dateadd (dd, filter.DaySupplyCumulative, filter.RxStartDate_base)
WHERE filter.[User] IS NULL
ORDER BY [User], Drug, RxStartDate_base
Maybe you need to optimize it by simplifying the logic. But be careful not to make an infinite loop. When debugging use OPTION (MAXRECURSION N) with N other than zero.

Populate column rows based on common name (subquery returns only one value)

I am trying to populate the blanks in CABSN column with the SN that matches the same name in TempName Column
TempName CabSN SN Name Order RowID
DevCab01 SN12345 SN12345 DevCab01 19 1
DevCab01 SN12346 Test2 18 2
DevCab01 SN12347 Test3 17 3
DevCab01 SN12348 Test4 16 4
DevCab01 SN12352 Test8 15 5
DevCab01 SN12353 Test9 14 6
DevCab01 SN12354 Test10 13 7
DevCab02 SN12355 SN12355 DevCab02 9 8
DevCab02 SN12356 Test12 8 9
DevCab02 SN12357 Test13 7 10
DevCab02 SN12358 Test14 6 11
DevCab03 SN12359 SN12359 DevCab03 5 12
DevCab03 SN12360 Test16 4 13
DevCab03 SN12361 Test17 3 14
DevCab04 SN12349 SN12349 DevCab04 15 15
DevCab04 SN12350 Test6 14 16
DevCab04 SN12351 Test7 13 17
My script attempt (which failed) at populating the blank rows in CabSN with the matching TempName
DECLARE #CabID AS nvarchar(50)
SET #CabID = NULL
(regardless where i had placed the variable it didn't work, displayed more than one value returned)
UPDATE m
set
m.[CabSN] =
CASE WHEN m.[CabSN] is NULL
THEN (
SELECT m3.[CabSN]
FROM [tblname1] m3
JOIN inserted i ON i.[TempName] = m3.[TempName]
WHERE m3.[RowID] =
(
SELECT MAX(i.RowID)
FROM [tblname1] m2
JOIN inserted i ON i.[TempName] = m2.[TempName]
WHERE m2.[RowID] < m.[RowID]
and m2.[CabSN] is not NULL)
)
ELSE m.[CabSN]
Full working example:
DECLARE #DataSource TABLE
(
[TempName] VARCHAR(12)
,[CabSN] VARCHAR(12)
,[SN] VARCHAR(12)
,[Name] VARCHAR(12)
,[Order] SMALLINT
,[RowID] SMALLINT
);
INSERT INTO #DataSource ([TempName], [CabSN], [SN], [Name], [Order], [RowID])
VALUES ('DevCab01', 'SN12345', 'SN12345', 'DevCab01', '19', '1')
,('DevCab01', '', 'SN12346', 'Test2', ' 18', '2')
,('DevCab01', '', 'SN12347', 'Test3', ' 17', '3')
,('DevCab01', '', 'SN12348', 'Test4', ' 16', '4')
,('DevCab01', '', 'SN12352', 'Test8', ' 15', '5')
,('DevCab01', '', 'SN12353', 'Test9', ' 14', '6')
,('DevCab01', '', 'SN12354', 'Test10', '13', '7')
,('DevCab02', 'SN12355', 'SN12355', 'DevCab02', '9', '8')
,('DevCab02', '', 'SN12356', 'Test12', ' 8', '9')
,('DevCab02', '', 'SN12357', 'Test13', ' 7', '10')
,('DevCab02', '', 'SN12358', 'Test14', ' 6', '11')
,('DevCab03', 'SN12359', 'SN12359', 'DevCab03', '5', '12')
,('DevCab03', '', 'SN12360', 'Test16', ' 4', '13')
,('DevCab03', '', 'SN12361', 'Test17', ' 3', '14')
,('DevCab04', 'SN12349', 'SN12349', 'DevCab04', '15', '15')
,('DevCab04', '', 'SN12350', 'Test6', ' 14', '16')
,('DevCab04', '', 'SN12351', 'Test7', ' 13', '17');
WITH DataSource AS
(
SELECT DISTINCT [TempName]
,[CabSN]
FROM #DataSource
WHERE [CabSN] <> ''
)
UPDATE #DataSource
SET [CabSN] = S.[CabSN]
FROM #DataSource T
INNER JOIN DataSource S
ON T.[TempName] = S.[TempName]
WHERE T.[CabSN] = '';
SELECT *
FROM #DataSource;

get a previous row in oracle on conditition

if I have a table which has the following table structure (id,username,send_date, message) how do I get a previous message for the different user via Oracle SQL
suppose I have following data
id, username, send_date ,message
1, user A , 12.02.2018 10:08:05 ,'problem 1'
2, user B , 12.02.2018 11:34:12 ,'what ?'
3, user B , 12.02.2018 14:12:02 ,'try this'
4, user A , 13.02.2018 09:29:23 ,'see here'
5, user B , 13.02.2018 13:34:12 ,'do this'
how do I get this instead
id, username, send_date ,message ,reply_to
1, user A , 12.02.2018 10:08:05 ,'problem 1' ,null
2, user B , 12.02.2018 11:34:12 ,'what ?' ,'problem1'
3, user B , 12.02.2018 14:12:02 ,'try this' ,'problem 1'
4, user A , 13.02.2018 09:29:23 ,'see here' ,'try this'
5, user B , 13.02.2018 13:34:12 ,'do this' ,'see here'
My query
select m.id, m.username, send_date, m.message,
lag(m.message) over (order by M.SEND_DATE) reply_to
from ts_messages m
order by m.send_date
returns this
id, username ,send_date ,message ,reply_to
1, user A ,12.02.2018 10:08:05 ,'problem 1' ,null
2, user B ,12.02.2018 11:34:12 ,'what ?' ,'problem1'
3, user B ,12.02.2018 14:12:02 ,'try this' ,'**what?**'
4, user A ,13.02.2018 09:29:23 ,'see here' ,'try this'
5, user B ,13.02.2018 13:34:12 ,'do this' ,'see here'
Basically, I need to display a message which I am replying to while writing a response, which is supposed to be the previous message written by someone other than myself
Here's one option which returns the desired result; though, doesn't seem to be very efficient as it accesses the source table several times. Though, if there aren't that many rows there, you probably won't see any difference from a hypothetical better solution (which I was unable to produce, but would really love to see).
SQL> with test (id, username, send_date, message) as
2 (select 1, 'user A', to_date('12.02.2018 10:08', 'dd.mm.yyyy hh24:mi'), 'problem 1' from dual union
3 select 2, 'user B', to_date('12.02.2018 11:34', 'dd.mm.yyyy hh24:mi'), 'what?' from dual union
4 select 3, 'user B', to_date('12.02.2018 14:12', 'dd.mm.yyyy hh24:mi'), 'try this' from dual union
5 select 4, 'user A', to_date('13.02.2018 09:29', 'dd.mm.yyyy hh24:mi'), 'see here' from dual union
6 select 5, 'user B', to_date('13.02.2018 13:34', 'dd.mm.yyyy hh24:mi'), 'do this' from dual
7 )
8 select
9 t.id,
10 t.username,
11 t.send_date,
12 t.message,
13 --
14 (select t2.message
15 from test t2
16 where t2.username <> t.username
17 and t2.id = (select max(t3.id)
18 from test t3
19 where t3.username <> t.username
20 and t3.id < t.id
21 )
22 ) reply_to
23 from test t
24 order by t.id;
ID USERNA SEND_DATE MESSAGE REPLY_TO
---------- ------ ---------------- --------- ---------
1 user A 12.02.2018 10:08 problem 1
2 user B 12.02.2018 11:34 what? problem 1
3 user B 12.02.2018 14:12 try this problem 1
4 user A 13.02.2018 09:29 see here try this
5 user B 13.02.2018 13:34 do this see here
SQL>

PostgreSQL, renumber and cumulative sum at once

I have temporary table (without primary key) created as a result of few operations which are UNION together and which can be simulated with following one:
DROP TABLE IF EXISTS temp1;
CREATE TEMP TABLE temp1(rownum int, sname text, input_qty decimal(8,3),
output_qty decimal(8,3), cumulativesum decimal(8,3));
INSERT INTO temp1 (rownum, sname, input_qty, output_qty, cumulativesum)
VALUES (0, 'name 1', 3.186, 0, 0),
(0, 'name 2', 0, 0.24, 0),
(0, 'name 3', 0, 1, 0),
(0, 'name 4', 0.18, 0.125, 0),
(0, 'name 5', 0, 1.14, 0);
During past processes columns 'rownum' and 'cumulativesum' was intentionally filled with zeroes.
As a last two steps (or one if possible) I would like to enumerate rownum by +1 from beginning and calculate and write cumulative sum in column 'cumulativesum' to get table ready to write to html document more or less directly.
Cumulative sum should be calculated like:
lastcumulstivesum + input_qty - output_qty.
After all this should be result of operation:
1, 'name 1' 3.186 0.000 3.186
2, 'name 2' 0.000 0.240 2.946
3, 'name 3' 0.000 1.000 1.946
4, 'name 4' 0.180 0.125 2.001
5, 'name 5' 0.000 1.140 0.861
Please if someone can write described query(es) with presented table.
PostgreSQL 9.1, Windows 7