how to insert rows from table to table using output - sql

i got two tables..i want to copy the same sets of data from the table to itself but in table2 i want to copy the id in table1 to table2 id2.
Table1
id group account
------------------------------
101 massive balls
201 nip ripper
301 holy magnum
Table 2
id title amount id2
-------------------------------------
1 expense 100.00 101
2 local 50.00 201
3 depart 25.00 301
here's what i already did but can't get the values of b.title and b.amount
INSERT INTO Table1
OUTPUT inserted.Id, B.title, B.amount
INTO Table2(id2, title, amount)
SELECT A.*,
B.title,
B.amount,
B.id2
FROM Table1 AS A
LEFT OUTER JOIN
(SELECT title,
amount,
id2
FROM Table2) AS B
ON A.id = B.id2
the data in the table after inserting should be like this. same sets of data from table 1 and 2 but only copied the id of table1 to table2 id2
Table1
id group account
------------------------------
101 massive balls
201 nip ripper
301 holy magnum
302 massive balls
303 nip ripper
304 holy magnum
Table 2
id title amount id2
-------------------------------------
1 expense 100.00 101
2 local 50.00 201
3 depart 25.00 301
4 expense 100.00 302
5 local 50.00 303
6 depart 25.00 304

Related

How to select the most recent records in a dataset in sql

I have a large dataset where we keep track of all revenue collected by client for each month. So each client gets a row for each month they were charged, resulting in a lot of rows. I am trying to find a way to pull the most recent record for each client.
Here is what i have:
merchant name
Merchant id
revenue date
revenue amount
fish
1234
2022-03-01
200
fish
1234
2022-04-01
200
fish
1234
2022-05-01
200
fish
1234
2022-06-01
200
dog
5678
2022-01-01
200
dog
5678
2022-02-01
200
dog
5678
2022-03-01
200
dog
5678
2022-04-01
200
cat
1011
2022-10-01
200
cat
1011
2022-11-01
200
My desired result is:
merchant name
Merchant id
revenue date
revenue amount
fish
1234
2022-06-01
200
dog
5678
2022-04-01
200
cat
1011
2022-11-01
200
I have tried this:
Select distinct
merchant_name,
merchant_id,
revenue_date,
revenue_amount
from table
where revenue_date=(select max(revenue_date) from table)
but that is only returning rows that match the maximum date listed (2022-11-01).
Any help is much appreciated!
The general solution takes the form:
select *
from (
select t.*, row_number() over(partition by merchant_name
order by revenue_date desc) as rn
from t
) x
where rn = 1
Or... in PostgreSQL you can just do:
select distinct on (merchant_name) *
from t
order by merchant_name, revenue_date desc
Alternate answer (formatted for SQL Server):
--For each merchantID, find the latest date
WITH maxDates AS (
SELECT
merchantID,
MAX(revenueDate) revenueDate
FROM #input
GROUP BY merchantID
)
--Use the defined CTE to retrieve the rest of the columns
SELECT i.*
FROM #input i
INNER JOIN maxDates m ON i.merchantID=m.merchantID AND i.revenueDate=m.revenueDate

Tracing original Value through Iteration SQL

Suppose there is a data collection system that, whenever a record is altered, it is then saved as a new record with a prefix (say M-[most recent number in que and is unique]).
Suppose I am given the following data set:
Customer | Original_Val
1 1020
2 1011
3 1001
I need to find the most recent value for each customer given the following table:
Customer | Most_Recent_Val | Pretained_To_Val | date
1 M-2000 M-1050 20170225
1 M-1050 M-1035 20170205
1 M-1035 1020 20170131
1 1020 NULL 20170101
2 M-1031 1011 20170105
2 1011 NULL 20161231
3 1001 NULL 20150101
My desired output would be:
Customer | Original_Val | Most_Recent_Val | date
1 1020 M-2000 20170225
2 1011 M-1031 20170105
3 1001 1001 20150101
For customer 1, there are 4 levels i.e (M-2000 <- M-1050 <- M-1035 <- 1020) Note that there would be no more than 10 levels of depth for each customer.
Much Appreciated! Thanks in advance.
Find the min and max of each customer and then join it together. Something like this:
Select
[min].Customer
,[min].Most_Recent_Val as Original_Val
,[max].Most_Recent_Val as Most_Recent_Val
,[max].date
From
(
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MIN(date) as MIN_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MIN_Date = t1.Date
) [min]
inner join (
Select
Customer
,Most_Recent_Val
,date
From
table t1
inner join (
Select
Customer
,MAX(date) as MAX_Date
From
table
Group By
Customer
) t2 ON t2.Customer = t1.Customer
and t2.MAX_Date = t1.Date
) [max] ON [max].Customer = [min].Customer

SQL Prevent Multiple Counting

I found some similar SO questions regarding my issue and they fixed it by using sub-queries but I can't seem to apply it on my situation.
Goal
My goal is to count the animals that have been a breeder at least once in their lifespan.
I have 2 tables to keep track of when an animal became a breeder. Here's a simple look of how the tables are structured:
Animals (a)
id name
-------------------
100 Mouse
101 Cow
102 Pig
103 Dog
Breeding History (bh)
id animal_id code date
--------------------------------------------
500 100 B 2016-01-12
501 100 A 2016-01-25
502 101 B 2016-01-28
503 102 B 2016-02-02
504 100 B 2016-02-05
505 100 A 2016-02-08
In this scenario, my current query for counting works fine for both 101 | Cow and 102 | Pig since they only became a breeder (Code: B) once. The count for an animal who never became a breeder is also correct but it's not really a problem here. For an animal that became a breeder more than once in its lifespan e.g. 100 | Mouse it would be counted by the number of times it became a breeder.
Query
SELECT
a.name,
COUNT(CASE WHEN bh.code IN ('B') THEN 1 ELSE NULL END) AS breeder_count
FROM animals a
LEFT OUTER JOIN breeding_history bh
ON a.id = bh.animal_id
GROUP BY a.name
Result
name breeder_count
--------------------------
Mouse 2
Cow 1
Pig 1
Dog 0
The result shows that there are 2 mice that became a breeder when actually it was the same animal and should only be counted once.
You can use the DISTINCT keyword, so as to count a 'B' just once:
SELECT
a.name,
COUNT(DISTINCT CASE WHEN bh.code IN ('B') THEN 1 END) AS breeder_count
FROM animals a
LEFT OUTER JOIN breeding_history bh
ON a.id = bh.animal_id
GROUP BY a.name
As a side note, ELSE NULL is redundant and has been removed from the CASE expression.
Demo here

Recursive sql with Left outer join in Teradata

I have a query that is using Table1 and Table2 with left outer join on 'usage'. Now i have to join that query with the Table3 with (I guess recursive sql) to generate the 'Resulting table'.
I saw lot of examples on recursive sql, but didnt find any thing that is using left outer join.
Now my existing query is like this
select PIN, startDt, StartTm, usage, Min
from Table1 t1 left Outer join Table2 t2 on t1.usage= t2.usage;
How can i do the Table3 with this query, so that ratGrp will be in comma separated way? Please help!!
Table1
PIN startDt StartTm usage Min
-----------------------------------------
123 08/03/2014 12:12:00 500 4567
234 08/04/2014 12:12:00 200 4568
.....
Table2
1stCol 2ndCol usage
------------------------
abc 234 500
Table3
PIN ratGrp
-----------------
123 3300
123 100
123 103
234 3300
234 550
Resulting table
PIN startDt StartTm usage Min ratGrp
-----------------------------------------------
123 08/03/2014 12:12:00 500 4567 3300,100,103
234 08/04/2014 12:12:00 200 4568 3300,550

How Do I Select All Parents and the Top Previous Child Record Based on Dates in SQL Server 2008

I'm using a vendor provided database running on SQL Server 2008. There are two tables that track tests. For every record in Table A there may be zero, one or multiple records in Table B. There can also be multiple tests in Table A for the same user. The relationship is TableA.UserID = TableB.UserID. Tests taken in Table B can occur before or after Table A.
I need to select all of the records in Table A and, if test(s) from Table B have been taken by the same user before the test in Table A, data from Table B but only from the last previous child record. Both tables are structured similarly:
**TABLE A**
TestID INTEGER PRIMARY KEY,
UserID INTEGER,
TestDate DATE,
Score INTEGER
TABLE B
TestID INTEGER PRIMARY KEY,
UserID INTEGER,
TestDate Date,
Score INTEGER
Sample Data
TABLE A
TestID UserID TestDate Score
1 100 2014-02-15 80
2 101 2014-02-20 100
3 102 2014-02-22 90
4 102 2014-03-10 70
TABLE B
TestID UserID TestDate Score
1000 100 2014-02-01 55
1007 100 2014-02-05 85
1012 100 2014-02-20 95
1034 102 2014-02-12 65
1205 102 2014-03-05 75
1986 101 2014-03-10 45
What I'd like returned would be:
UserID TestA_ID TestADate TestAScore TestB_ID TestBDate TestBScore
100 1 2014-02-15 80 1007 2014-02-05 85
101 2 2014-02-20 100 NULL NULL NULL
102 3 2014-02-22 90 1034 2014-02-12 65
102 4 2014-03-10 70 1205 2014-03-05 75
I've know how to get all of the previous Table B rows joined to the Table A rows by using a LEFT OUTER JOIN and filtering by date in the WHERE clause, and I know how to get the Top row from Table B, but I haven't been able to work out how to get the top child record that occurs before the date of the record in Table A. Any help would be appreciated. Thanks.
You can do this using OUTER APPLY in T-SQL.
For each record in TableA, we're looking for a record in TableB for the same user but with a test date prior to the test date in TableA and we're also ordering the test in TableB to ensure we're getting the most recent test from TableB (but still prior to the test date from TableA).
SELECT
A.[UserID],
A.[TestID] [TestA_ID],
A.[TestDate] [TestADate],
A.[Score] [TestAScore],
B.[TestB_ID],
B.[TestBDate],
B.[TestBScore]
FROM [TableA] A
OUTER APPLY
(
SELECT TOP 1
B1.[TestID] [TestB_ID],
B1.[TestDate] [TestBDate],
B1.[Score] [TestBScore]
FROM [TableB] B1
WHERE A.[UserID] = B1.[UserID]
AND A.[TestDate] > B1.[TestDate]
ORDER BY
B1.[TestDate] DESC
) B
Or another option might be to use the ROW_NUMBER() window function to find the record from TableB. I have a hunch this one wouldn't perform as well because it needs to hit TableA twice, but can't be sure without running tests.
SELECT
A.[UserID],
A.[TestID] [TestA_ID],
A.[TestDate] [TestADate],
A.[Score] [TestAScore],
B.[TestB_ID],
B.[TestBDate],
B.[TestBScore]
FROM [TableA] A
LEFT JOIN
(
SELECT
ROW_NUMBER() OVER (PARTITION BY A.[UserID], A.[TestID] ORDER BY B.[TestDate] DESC) [rn],
A.[UserID],
A.[TestID] [TestA_ID],
B.[TestID] [TestB_ID],
B.[TestDate] [TestBDate],
B.[Score] [TestBScore]
FROM [TableA] A
INNER JOIN [TableB] B
ON A.[UserID] = B.[UserID]
AND A.[TestDate] > B.[TestDate]
) B
ON A.[UserID] = B.[UserID]
AND A.[TestID] = B.[TestA_ID]
AND B.[rn] = 1