I am trying to formulate a SQL to pick specific values from a column based on the boundary conditions. (DDLs Below).
Below is the expected output:
Explanation:
For the first row with Session_id (A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899) the action type would be None because it is neither selectSearchHistory or selectISS as in row number 2 and 3.
But for row 2, I have action_type selectSearchHistory and hence I pull in that value, rest remaining the same. For the 3rd row, I have selectISS and hence I pull that value, rest remaining the same
Here's what I have done so far:
select session_id,
lag(action_type) over (partition by cust_id, device_event_date order by session_id) as prev_action_type,
tbl_name, marketplace_id, enc_customer_id, device_event_date, page_type, action_type,
ROW_NUMBER () over (partition by session_id order by session_id ) as rn
from test_table where action_type is NOT NULL;
I am not able to group them into a per action_type row as show in the image.
create table test_table (session_id varchar(200), table_name varchar(100), page_type varchar(100), action_type varchar(100), territory varchar(100), cust_id varchar(100), device_event_date timestamp);
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','page_view','browseFind','','1','A1XYZB0','44270.6986909606');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','page_view','browseSearch','','1','A1XYZB0','44270.6987389699');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','clicks','browseSearch','initiateSearch','1','A1XYZB0','44270.6987484028');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','clicks','browseSearch','executeSearch','1','A1XYZB0','44270.6988179745');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','page_view','browseSearch','','1','A1XYZB0','44270.698827581');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','clicks','searchResults','playSong','1','A1XYZB0','44270.6989970139');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:46:06.899','plbk_attr_search','searchResults','','1','A1XYZB0','44270.6989970139');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','page_view','browseFind','','1','A1XYZB0','44270.7023368287');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','page_view','browseSearch','','1','A1XYZB0','44270.7023457292');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','clicks','browseSearch','selectSearchHistory','1','A1XYZB0','44270.7025611227');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','clicks','browseSearch','executeSearch','1','A1XYZB0','44270.7025611227');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','page_view','browseSearch','','1','A1XYZB0','44270.7025758102');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','clicks','searchResults','selectAlbum','1','A1XYZB0','44270.7026314236');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:51:21.902','plbk_attr_search','searchResults','','1','A1XYZB0','44270.7026314236');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','page_view','browseFind','','1','A1XYZB0','44270.7054355556');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','page_view','browseSearch','','1','A1XYZB0','44270.7054554398');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','clicks','browseSearch','initiateSearch','1','A1XYZB0','44270.7054703241');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','clicks','browseSearch','selectISS','1','A1XYZB0','44270.7055178704');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','clicks','browseSearch','executeSearch','1','A1XYZB0','44270.7055178704');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','page_view','browseSearch','','1','A1XYZB0','44270.7055278241');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','clicks','searchResults','playSong','1','A1XYZB0','44270.7055589236');
INSERT INTO test_table VALUES('A1XYZB0-A2825NDLA7WDZV-2021-03-15 16:55:49.632','plbk_attr_search','searchResults','','1','A1XYZB0','44270.7055589236');
The device_event_time stamp is epoch.
Not entirely sure about your data or requirements, but here's a CTE approach that produces the output in your example...
WITH ssh AS
(
SELECT session_id, action_type
FROM test_table
WHERE action_type = 'selectSearchHistory'
), siss AS
(
SELECT session_id, action_type
FROM test_table
WHERE action_type = 'selectISS'
), s AS
(
SELECT session_id, territory, cust_id
FROM test_table
GROUP BY session_id, territory, cust_id
)
SELECT
s.session_id,
COALESCE(ssh.action_type, COALESCE(siss.action_type, 'None')) AS action_type,
s.territory,
s.cust_id
FROM s
LEFT JOIN ssh ON ssh.session_id = s.session_id
LEFT JOIN siss ON siss.session_id = s.session_id;
Click here to see it in action & have a play in SQL Fiddle
Related
I have two temp_tables defined as:
with temp_table_1 as (
select id from table_A where fname="john" limit 1
),
with temp_table_2 as (
select id from table_B where lname="smith" limit 1
)
These tables returns 1 row with just the id. I want to Insert a row into table_C where the column col_1 is equal to the result of temp_table_1 and the column col_2 is equal to the result of temp_table_2, and the third column (created_at) set to now:
The following fails for me:
insert into table_c (col_1, col_2, created_at)
values (temp_table_1.id, temp_table_2.id, current_timestamp at time zone 'UTC');
BEGIN;
CREATE temp TABLE table_a (
id bigint,
fname text
);
CREATE temp TABLE table_b (
id bigint,
lname text
);
CREATE temp TABLE table_c (
col_1 bigint,
col_2 bigint,
created_at timestamp
);
INSERT INTO table_a
VALUES (1, 'john');
INSERT INTO table_a
VALUES (1, 'john');
INSERT INTO table_b
VALUES (2, 'smith');
INSERT INTO table_b
VALUES (2, 'smith');
COMMIT;
WITH temp_table_1 AS (
SELECT
a.id AS a_id,
b.id AS b_id
FROM
table_a a,
table_b b
WHERE
a.fname = 'john'
AND b.lname = 'smith'
LIMIT 1)
INSERT INTO table_c (col_1, col_2, created_at)
SELECT
temp_table_1.a_id,
temp_table_1.b_id,
CURRENT_TIMESTAMP at time zone 'UTC'
FROM
temp_table_1
RETURNING
*;
That should be fairly straightforward with a cross join:
WITH temp_table_1 AS (... LIMIT 1),
WITH temp_table_2 AS (... LIMIT 1)
INSERT INTO table_c (col_1, col_2, created_at)
SELECT temp_table_1.id,
temp_table_2.id,
current_timestamp AT TIME ZONE 'UTC'
FROM temp_table_1 CROSS JOIN temp_table_2;
CREATE TABLE `testskm`(
`mem_id` NUMBER(5) NOT NULL,
`mem_sal` NUMBER(5) NOT NULL);
insert into `testskm` values (1,100);
insert into `testskm` values (1,200);
insert into `testskm` values (2,350);
insert into testskm values (2,150);
insert into testskm values (3,12);
insert into testskm values (1,300);
insert into testskm values (2,50);
insert into testskm values (3,13);
insert into testskm values (3,14);
insert into testskm values (3,15);
i have insert statements for mem_id 1,2, & 3. I want to get the last 2 inserted records in the table for all mem_id.
I have the tried the below code , but its giving me only records based on the mem_sal as i used the order by..
select * from(
select
mem_id, mem_sal,
--max(sysdate) over (partition by mem_id) latest,
rank() over( partition BY mem_id order by mem_sal ) RISK_ORDER
from testskm)
where RISK_ORDER <= 2
i want output of these inserted records:
insert into `testskm` values (1,200);
insert into `testskm` values (1,300);
insert into `testskm` values (2,150);
insert into `testskm` values (2,50);
insert into `testskm` values (3,14);
insert into `testskm` values (3,15);
SQL tables represent unordered sets. There is no "last two rows" unless a column specifies the ordering. Your table has no such column.
You can define one. In MySQL, this looks like:
create table `testskm` (
testskm_id int auto_increment primary key,
`mem_id` int NOT NULL,
`mem_sal` int NOT NULL
);
Then you can use row_number():
select ts.*
from (select ts.*, row_number() over (partition by mem_id order by testskm_id desc) as seqnum
from testskm ts
) ts
where seqnum <= 2;
Here is a db<>fiddle.
First, SQL is NOT my strong point, as you'll see. I have one table that keeps track of the next item number, by some type, like so:
declare #maxs as table
(
Equip int,
NextId int
);
-- initial id values
insert into #maxs (Equip, NextId) values (400, 40);
insert into #maxs (Equip, NextId) values (500, 50);
If I create an item of type '400' then the next Id is 40, and that should be incremented to 41. In a case of a single add, that's easy enough. Our program does adds in batch, so here is my problem.
declare #t as table (Id int, Equip int, Descr varchar(20));
-- simulates the batch processing
insert into #t (Equip, Descr) values (400, 'Item 1');
insert into #t (Equip, Descr) values (400, 'Item 2');
insert into #t (Equip, Descr) values (500, 'Item 3');
-- generate the new id's in batch
UPDATE t
SET Id = (SELECT m.NextId + ROW_NUMBER() OVER (PARTITION BY t.Equip ORDER BY t.Equip))
FROM #t t
INNER JOIN #maxs m ON m.Equip = t.Equip
SELECT * FROM #t
This results in both Item 1 and Item 2 having the same Id because only 1 row is returned for 400, so ROW_NUMBER is the same for both. I need to be able to increment the NextId value in #maxs as well as update the entry in #t so that the second row that joins into the 400 value in #maxs will have the next value (almost like a x++ reference in c#). Is there a clean way to do that in SQL?
Thanks in advance.
Just go with JOIN and nested select
declare #t as table (Id int, Equip int, Descr varchar(20));
-- simulates the batch processing
insert into #t (Equip, Descr) values (400, 'Item 1');
insert into #t (Equip, Descr) values (400, 'Item 2');
insert into #t (Equip, Descr) values (500, 'Item 3');
-- generate the new id's in batch
UPDATE t
SET
Id = t.Equip + s.RowNum
FROM #t t
JOIN (select Equip,
Descr,
ROW_NUMBER() OVER (PARTITION BY Equip ORDER BY Equip) RowNum
from #t) s
on t.Equip = s.Equip and t.Descr = s.Descr
select * from #t
And if possible, try to switch from table variable to temporary table
You can do what you want with a CTE:
WITH toupdate as (
SELECT t.*,
ROW_NUMBER() OVER (PARTITION BY t.Equip ORDER BY t.Equip) as seqnum
FROM #t t
UPDATE t
SET
Id = m.NextId + seqnum
FROM toupdate t INNER JOIN
#maxs m
ON m.Equip = t.Equip;
I'm not sure this is a good idea, though. It is better to use identity columns to identify each row. There are definitely some cases, though, where numbering within a group is useful as a secondary key (for instance, line items on an invoice).
I need to get a row of information with max timestamp in postgresql. Below is a demo for this question:
drop table Mytable cascade
create table MyTable (usr char(1), event_dt timestamp without time zone);
insert into mytable values ('A','01-JAN-2009 11:10:11');
insert into mytable values ('A','02-JAN-2009 11:10:22');
insert into mytable values ('B','02-JAN-2009 01:01:59' );
insert into mytable values ('C', '31-DEC-2008 02:02:02');
insert into mytable values ('D', '31-DEC-2008 03:03:03');
If I do
select max(event_dt) from (
select usr,event_dt from mytable where usr= 'A') as foo
It is sort of what I need but it only returns the event_dt
"2009-01-02 11:10:22"
Where I want the usr as well sa event_dt from that row. How do I do it?
I would simply go for...
SELECT usr, event_dt FROM mytable ORDER BY event_dt DESC LIMIT 1
Is This Possible?
Here is something I'm looking for, executed together:
First, it would execute the INSERT based on how many rows in the SELECT
INSERT INTO TABLE2 (xID, NAME)
SELECT xID, NAME FROM TABLE
Then getting the ##IDENTITY of each INSERTED ROW, it would create a new Insert including the same data of the first SELECT statement:
INSERT INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME, ID as Scope_IdentitY()
If not, what the best way without using cursor or while?
You have, at least, two options:
1) The OUTPUT...INTO target_table clause (SQL2005+)
2) Or you could write composable DML(SQL2008+).
Example:
DECLARE #Table2 TABLE(
ID INT IDENTITY PRIMARY KEY, --IDENTITY
xID INT NOT NULL,
NAME VARCHAR(25) NOT NULL
);
DECLARE #Table3 TABLE(
ID INT PRIMARY KEY, --No IDENTITY
xID INT NOT NULL,
NAME VARCHAR(25) NOT NULL
);
--First solution: OUTPUT ... INTO
INSERT INTO #Table2 (xID, NAME)
OUTPUT inserted.xID, inserted.NAME, inserted.ID INTO #Table3(xID, NAME, ID)
SELECT t.Col1, t.Col2
FROM (SELECT 11,'A' UNION ALL SELECT 22,'B' UNION ALL SELECT 33,'C') AS t(Col1,Col2);
--Second solution: composable DML
INSERT INTO #Table3(xID, NAME, ID)
SELECT src.xID, src.NAME, src.ID
FROM
(
INSERT INTO #Table2 (xID, NAME)
OUTPUT inserted.xID, inserted.NAME, inserted.ID
SELECT t.Col1, t.Col2
FROM (VALUES(44,'D'),(55,'E'),(66,'F')) AS t(Col1,Col2)
) src
SELECT * FROM #Table2
SELECT * FROM #Table3
INSERT INTO TABLE2 (xID, NAME)
OUTPUT
INSERTED.xID, INSERTED.NAME, INSERTED.ID
INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME FROM [TABLE]
You can declare a table variable and store the output of the rows inserted into dbo.Table2 in this variable and use the table variable as the input for table dbo.Table3.
CREATE TABLE dbo.Table1
(
xid int NOT NULL
, name varchar(30) NOT NULL
);
CREATE TABLE dbo.Table2
(
id int NOT NULL IDENTITY
, xid int NOT NULL
, name varchar(30) NOT NULL
);
CREATE TABLE dbo.Table3
(
id int NOT NULL
, xid int NOT NULL
, name varchar(30) NOT NULL
);
INSERT INTO dbo.Table1 (xid, name) VALUES
(195, 'abc'),
(242, 'def'),
(332, 'ghi');
GO
DECLARE #tempTable table
( id int
, xid int
, name varchar(30)
);
INSERT dbo.Table2
OUTPUT INSERTED.id, INSERTED.xid, INSERTED.name
INTO #tempTable
SELECT xid, name FROM dbo.Table1;
INSERT dbo.Table3 (id, xid, name)
SELECT id, xid, name FROM #tempTable;
SELECT id, xid, name FROM dbo.Table2;
SELECT id, xid, name FROM dbo.Table3;
GO
OK, based on your comments below, try this:
INSERT INTO TABLE2 (xID, NAME)
SELECT xID, NAME FROM TABLE;
INSERT INTO TABLE3 (xID, NAME, ID)
SELECT xID, NAME, ##identity
FROM TABLE2;
Assuming these table structures:
TABLE_A
-----------
X_ID
NAME
TABLE_B
----------------
TABLE_B_ID [PK]
X_ID
NAME
TABLE_C
----------------
TABLE_C_ID [PK]
X_ID
NAME
TABLE_B_ID [FK]
Then wouldn't this work (best in a transaction)?:
-- Grab data from TABLE_A and INSERT INTO TABLE_B
INSERT INTO TABLE_B (
X_ID,
NAME
)
SELECT
X_ID,
NAME
FROM
TABLE_A
-- Grab data from TABLE_B that matches the data imported from TABLE_A
-- and INSERT that data into TABLE_C (incl. the PK from TABLE_B)
INSERT INTO TABLE_C (
X_ID,
NAME,
TABLE_B_ID
)
SELECT
b.X_ID,
b.NAME,
b.TABLE_B_ID
FROM
TABLE_B b
INNER JOIN
TABLE_A a ON a.X_ID = b.X_ID