Insert table1 row values into table2 columns in SQL - sql

I'm about to write a query and was thinking if anybody can help me out.Please have a look at attached image and at the same time let me tell you brief overview of my requirement.
Table1 Screenshot
Table2 Screenshot
In Table1, we can have maximum 4 and minimum 2 records per user per day. If a user have 4 records then FirstRecord of the day In Table1 will go to Time1 column in Table2, second will go to Time2 and so on. If a user have 2 records per day than First record of the day will go to Time2 column in Table2 and second record will go to Time3 column. For references, Tables screen shots are attached.
Any useful link or query would be appreciated

Use ROW_NUMBER() and partition by UserID and order by TransactionDate to generate numbers 1-4 or 1-2 for each user.
Then insert into Table 2 with a CASE expression for each of the four time columns.
The CASE will check a subquery to get the MAX(RowNumber) for that User, and then SELECT the appropriate row from Table 1 based on the logic you gave for the two cases.

Related

SQL for append rows based on max date

This is more of a logic question as I am having a hard time wrapping my head around it.
Say I have table 1 that is truncated and populated everyday, and a time stamp column is added onto it. Everyday new records would be added to the table.
That table 1 is copied to table 2 initially, however on consequent runs I only want to add the new records from table 1 into table 2.
I know this will be a mixture of matching the columns and only importing the MAX DATES, however confused as to the actual logic of the query.
So in short I want to append only the latest rows from table 1 to table 2 based on the max date.
If you want to sync the tables daily, you may just look for timestamp_column > current_Date.
If you want to get the max dates, you can write something like this:
INSERT INTO table2 (x,y,z, timestamp_column)
SELECT x,y,z, current_timestamp() FROM table1
WHERE timestamp_column >
(SELECT IFNULL(MAX(timestamp_column), '0001-01-01' ) FROM table2);
On the other hand, I think Snowflake streams are a very good fit for this task:
https://docs.snowflake.com/en/user-guide/streams-intro.html
You can create an "Append-only" stream on table1, and use it as a source when synchronizing to table2.

Remove all non-duplicate rows based on a single column in a SQL Server table where there conditions on multiple columns for the select statement

I am attempting to pull data from a SQL Server table that meets certain criteria. Part of that criteria is that there can be multiple rows with the same data in my column and I need all of those rows returned...what I do not want are rows returned that are distinct.
I want to find a session that is in a specific date range, and meets one of two types of action, and are multiple, meaning there are two or more rows for the session.
Example SQL query:
SELECT activity and message
FROM myTable
WHERE (date BETWEEN '1/1/2020' and '1/31/2020')
AND activity IN ('trace', 'info')
Can you advise how I can grab the rows that meet my criteria of being in the correct date range and with the correct activity, but that have multiple rows only. I want no data that does not meet those three criteria.
Update to Body:
In creating the example query in my initial post, I neglected to include the label column. So the SELECT should read "SELECT activity, label and message FROM myTable WHERE (date BETWEEN '1/1/2020' and '1/31/2020') AND activity IN ('trace','info')". Based on sample data, I would expect the following return:
activity message label
-------- ------- -----
trace logged 1234
info written 1234
Label '1234' is the only value that meets all criteria: falls in the date range, meets activity values and has multiple rows.
With the limited information I could only make a wild guess and see if something like below works for you.
SELECT activity,
message,
COUNT(*) AS Count
FROM myTable
WHERE date BETWEEN '1/1/2020' and '1/31/2020'
AND activity IN ('trace', 'info')
AND message IN ('logged', 'written')
GROUP BY activity,
message
HAVING COUNT(*) > 1
ORDER BY Count DESC

Best way to compare two tables in SQL by matching string?

I have a program where the goal is to take data from an API, and capture the differences in data from minute to minute. It involves three tables: Table 1 (for new data), Table 2 (for previous minutes data), Results table (for the results).
The sequence of the program is like this:
Update table 1 -> Calculate the differences from table 2 and update a "Results" table with the differences -> Copy table 1 to table 2.
Then it repeats! It's simple and it works.
Here is my SQL query:
Insert into Results (symbol, bid, ask, description, Vol_Dif, Price_Dif, Time) Select * FROM(
Select symbol, bid, ask, description, Vol_Dif, Price_Dif, '$now' as Time FROM (
Select t1.symbol, t1.bid, t1.ask, t1.description, (t1.volume - t2.volume) AS Vol_Dif, (t1.totalPrice - t2.totalPrice) AS Price_Dif
FROM `Table_1` t1
Inner Join (
Select id, volume, ask, totalPrice FROM Table_2) t2
ON t2.id = t1.id) as test
The tables are identical in structure, obviously. The primary key is the 'id' field that auto-increments. And as you can see, I am comparing both tables on the basis of these 'id' fields being equal.
The PROBLEM is that the API seems to be inconsistent. One API call will have 50,000 entries. The next one will have 51,000 entries. And the entries are not just added to the end or added to the beginning, they are mixed into the middle.
So, comparing on equal ID's means I am comparing entries for DIFFERENT data, IF the API calls return a different number entries.
The data that I am trying to get the differences of is the 'bid', 'ask', 'Vol_Dif', 'Price_Dif' from minute to minute. There are many instances of the same 'symbol's, so I couldn't compare with this. The ONLY other way to compare entries from table to table, beside the matching ID's, would be matching the "description" fields.
I have tried this. The script is almost the same as above except the end of the query is
ON t2.description = t1.description
The problem is that looking for matching description fields takes 3 minutes for 50,000 entries, whereas looking for matching ID's takes 1 second.
Is there a better, faster way to do what I'm trying to do? Thanks in advance. Any help is appreciated.

DB2 - select last inserted 5 rows from a table

I have a table that has no indexed rows, nor a specific column...
Let's say "City, PersonName, PersonAge". I need to obtain the last 5 people inserted in that table...
How can I do it in in DB2?
I tried
select * from PEOPLE fetch first 5 rows only
this work perfectly... but no idea how to do it with the LAST rows....
You can't select the last 5 rows inserted, the database doesn't keep track of this. You need some sort of autoincremented ID or timestamp and order by that column descending.

Return rows in the exact order they were inserted

I have a simple join table with two id columns in SQL Server.
Is there any way to select all rows in the exact order they were inserted?
If I try to make a SELECT *, even if I don't specify an ORDER BY clause, the rows are not being returned in the order they were inserted, but ordered by the first key column.
I know it's a weird question, but this table is very big and I need to check exactly when a strange behavior has begun, and unfortunately I don't have a timestamp column in my table.
UPDATE #1
I'll try to explain why I'm saying that the rows are not returned in 'natural' order when I SELECT * FROM table without an ORDER BY clause.
My table was something like this:
id1 id2
---------------
1 1
2 2
3 3
4 4
5 5
5 6
... and so on, with about 90.000+ rows
Now, I don't know why (probably a software bug inserted these rows), but my table have 4.5 million rows and looks like this:
id1 id2
---------------
1 1
1 35986
1 44775
1 60816
1 62998
1 67514
1 67517
1 67701
1 67837
...
1 75657 (100+ "strange" rows)
2 2
2 35986
2 44775
2 60816
2 62998
2 67514
2 67517
2 67701
2 67837
...
2 75657 (100+ "strange" rows)
Crazy, my table have now millions of rows. I have to take a look when this happened (when the rows where inserted) because I have to delete them, but I can't just delete using *WHERE id2 IN (strange_ids)* because there are "right" id1 columns that belongs to these id2 columns, and I can't delete them, so I'm trying to see when exactly these rows were inserted to delete them.
When I SELECT * FROM table, it returns me ordered by id1, like the above table, and
the rows were not inserted in this order in my table. I think my table is not corrupted because is the second time that this strange behavior happens the same way, but now I have so many rows that I can delete manually like it was on 1st time. Why the rows are not being returned in the order they were inserted? These "strange rows" were definetely inserted yesterday and should be returned near the end of my table if I do a SELECT * without an ORDER BY, isn't it?
A select query with no order by does not retrieve the rows in any particular order. You have to have an order by to get an order.
SQL Server does not have any default method for retrieving by insert order. You can do it, if you have the information in the row. The best way is a primary key identity column:
TableId int identity(1, 1) not null primary key
Such a column is incremented as each row is inserted.
You can also have a CreatedAt column:
CreatedAt datetime default getdate()
However, this could have duplicates for simultaneous inserts.
The key point, though, is that a select with no order by clause returns an unordered set of rows.
As others have already written, you will not be able to get the rows out of the link table in the order they were inserted.
If there is some sort of internal ordering of the rows in one or both of the tables that this link table is joining, then you can use that to try to figure out when the link table rows have been created. Basically, they cannot have been created BEFORE both of the rows containing the PK:s have been created.
But on the other hand you will not be able to find out how long after they have been created.
If you have decent backups, you could try to restore one or a few backups of varying age and then try to see if those backups also contains this strange behaviour. It could give you at least some clue about when the strangeness has started.
But the bottom line is that using just a select, there is now way to get the row out of a table like this in the order they were inserted.
If SELECT * doesn't return them in 'natural' order and you didn't insert them with a timestamp or auto-incrementing ID then I believe you're sunk. If you've got an IDENTITY field, order by that.
But the question I have is, how can you tell that SELECT * isn't returning them in the order they were inserted?
Update:
Based on your update, it looks like there is no method by which to return records as you wish, I'd guess you've got a clustered index on ID1?
Select *, %%physloc%% as pl from table
order by pl desc