Find sequential child rows that have amounts which add up to parent row's amount - sql

I have a table like following
ID DATE ACCT TYPE AMOUNT SEQ CHK# TRC
1 6/5/2014 1234 C 10,000 1 1001
2 6/5/2014 3333 3,000 2 123 1002
3 6/5/2014 4444 5,000 3 234 1003
4 6/5/2014 5555 2,000 4 345 1004
5 6/5/2014 2345 C 3,000 1 1007
6 6/5/2014 5555 2,500 2 255 1008
7 6/5/2014 7777 500 3 277 1009
8 6/6/2014 1234 C 5,000 1 2001
9 6/6/2014 7777 3,000 2 278 2002
10 6/6/2014 8888 2,000 3 301 2003
The rows with TYPE = C are parent rows to the child rows that follow sequentially.
The parent rows do not have CHK# and child rows do have CHK#. Each
parent row has seq# = 1 and child rows have sequential numbers. (if it
matters) From above table, row ID 1 is the parent row to the rows with
ID 2 ~ 4. The AMOUNT on the child rows add up to the parent row's
amount.
Querying for transaction for date of '6/5/2014' on account # 2345 with
the amount of 3,000 - result should be rows with ID 6 and 7.
Is such query possible using MS-SQL 2008? If so, could you let me
know?

Well, based on the data that you have, you can use the id column to find the rows that you want. First, look for the one that has the check in that amount. The look for the subsequent ids with the same group. How do you define the group? That is easy. Take the difference between id and seq. This difference is constant for the parent and child rows.
So, here is goes:
select t.*
from table t
where (t.id - t.seq) = (select t2.id - t2.seq
from table t2
where t2.type = 'C' and
t2.acct = '2345' and
t2.date = '6/5/2014'
) and
t.type is null;

Related

Convert This SQL Query to ANSI SQL

I would like to convert this SQL query into ANSI SQL. I am having trouble wrapping my head around the logic of this query.
I use Snowflake Data Warehouse, but it does not understand this query because of the 'delete' statement right before join, so I am trying to break it down. From my understanding the row number column is giving me the order from 1 to N based on timestamp and placing it in C. Then C is joined against itself on the rows other than the first row (based on id) and placed in C1. Then C1 is deleted from the overall data, which leaves only the first row.
I may be understanding the logic incorrectly, but I am not used to seeing the 'delete' statement right before a join. Let me know if I got the logic right, or point me in the right direction.
This query was copy/pasted from THIS stackoverflow question which has the exact situation I am trying to solve, but on a much larger scale.
with C as
(
select ID,
row_number() over(order by DT) as rn
from YourTable
)
delete C1
from C as C1
inner join C as C2
on C1.rn = C2.rn-1 and
C1.ID = C2.ID
The specific problem I am trying to solve is this. Let's assume I have this table. I need to partition the rows by primary key combinations (primKey 1 & 2) while maintaining timestamp order.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
101 3 6 506 236 2005-10-25
100 1 2 302 423 2002-08-15
101 3 6 506 236 2008-12-05
101 3 6 300 100 2010-06-10
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
100 1 2 302 423 2003-07-24
Once the rows are partitioned and the timestamp is ordered within each partition, I need to delete the duplicate checkVar combination (checkVar 1 & 2) rows until the next change. Thus leaving me with the earliest unique row. The rows with asterisks are the ones which need to be removed since they are duplicates.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
*100 1 2 302 423 2002-08-15
*100 1 2 302 423 2003-07-24
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
101 3 6 506 236 2005-10-25
*101 3 6 506 236 2008-12-05
101 3 6 300 100 2010-06-10
This is the final result. As you can see for ID=100, even though the 1st and 3rd record are the same, the checkVar combination changed in between, which is fine. I am only removing the duplicates until the values change.
ID primKey1 primKey2 checkVar1 checkVar2 theTimestamp
100 1 2 302 423 2001-07-13
100 1 2 407 309 2005-09-05
100 1 2 302 423 2012-05-09
101 3 6 506 236 2005-10-25
101 3 6 300 100 2010-06-10
If you want to keep the earliest row for each id, then you can use:
delete from yourtable yt
where yt.dt > (select min(yt2.dt)
from yourtable yt
where yt2.id = yd.id
);
Your query would not do this, if that is your intent.

Combine 2 queries into 1 table with user entering the parameters twice for both queries

My project needs me to come up with a query which can compare any 2 months data side by side, by just keying in the dates of the 2 months.
I have done 2 separate queries that can only do single month data because I can only enter 1 date per query. I tried to combine this 2 separate query into 1 single query by selecting the columns from each table but it gives me blank data.
I will need some help in combining the 2 queries together, into 1 table as a view form and allowing the user to key in the 2 dates they want to get their data from. Below will be the 2 queries result I can achieve and also the end result I want to achieve from combining this 2 queries.
Conditions to merge the two table is that the company will be the same for both dates, and the item the company bought (if any). If the company did not buy the item on the month , data should be blank.
Query 1 : User will enter "First month" they want the data from
Inv Number Company Date Item Price Quantity Total
123 ABC 1/1/2018 Table 5 3 15
123 ABC 1/1/2018 Chair 2 4 8
345 XYZ 1/1/2018 Table 5 5 25
345 XYZ 1/1/2018 Chair 2 6 12
Query 2: User will enter "Second Month" they want the data from
Inv Number Company Date Item Price Quantity Total
999 ABC 1/2/2018 Table 4 3 12
999 ABC 1/2/2018 Chair 2 5 10
899 XYZ 1/2/2018 Table 4 3 12
End result : User will be allowed to key in both dates they want the data from
Inv Number Company Date Item Price Quantity Total Date Item Price Quantity Total Inv Number
123 ABC 1/1/2018 Table 5 3 15 1/2/2018 Table 4 3 12 999
123 ABC 1/1/2018 Chair 2 4 8 1/2/2018 Chair 2 5 10 999
345 XYZ 1/1/2018 Table 5 5 25 1/2/2018 Table 4 3 12 899
345 XYZ 1/1/2018 Chair 2 6 12

Selecting the last instance of the record but returning the first instance of it

I have table that consist logs of calls.
callid calling_pty dialed_num disposition dispvdn segment ucid
3862073 25555366 1001 1 1001 1 10000080561437527378
3862073 291113 1015 2 1015 2 10000080621437527416
3862074 635444419 1001 3 1001 1 10000081311437527892
3862075 25555596 1001 1 1001 1 10000081211437527803
3862075 26669 1014 3 1014 2 10000081231437527820
3862076 23044442 1009 2 1009 1 10000080961437527654
3862079 632444419 1001 1 1001 1 10000081361437527904
3862089 0111808 1001 1 1001 1 10000081671437528068
3862091 02366674 1001 1 1001 1 10000081011437527679
3862091 26666 1015 2 1015 2 10000081091437527712
3862097 63255529 1001 1 1001 1 10000081721437528139
3862097 29111 1014 3 1014 2 10000081771437528168
Given the sample data, I need to select the records with disposition = 3, but I need to check first if it has an earlier segment [disposition is the status of the call, 3 for abandon and segment is the number of call instances if it is transferred or not in one transaction]. and return the calling_pty(caller number) of the first instance, hence if there is none, it will return the number of that record. And it can be identifiend with the help of the callid
So with the given sample,
3862075 25555596 1001 1 1001 1 10000081211437527803
3862075 26669 1014 3 1014 2 10000081231437527820
it will return to me "25555596", they have the same callid but different calling party which would mean the call was transferred and then it was abandoned.
Therefore: the resulting record should be the "25555596" record.
*This would apply to all records of the same conditions and it will be populated as a list
3862074 635444419 1001 3 1001 1 10000081311437527892
3862075 25555596 1001 1 1001 1 10000081211437527803
3862097 63255529 1001 1 1001 1 10000081721437528139
*this will be the end result for the sample data
I did a nested select but im on the dead end of how I will check for the first instance. is there a sql function to achieve this?
I used two correlated sub-queries:
SELECT callid,
(SELECT calling_pty
FROM Log l
WHERE Log.callid = l.callid AND
segment = (SELECT MIN(segment)
FROM Log l2
WHERE l.callid = l2.callid)
)[calling_pty],
dialed_num, disposition, dispvdn, segment, ucid
FROM Log
WHERE disposition = 3
SQL Fiddle Demo

How to copy a table but randomise the rows with respect to one of the columns?

Does anyone know how can I mix up the data order while insert the records into another table in SQL?
Example:
I have 2 tables, Table A and Table B, I would like to insert the record from Table A to Table B, how ever I would like the records mix up while insert into Table B insert of follow the order in Table A. Will it be possible to do it in SQL?
Table A:
ID Postcode Total
1 3000 10
2 3000 20
3 3000 5
4 3001 10
5 3001 6
6 3002 6
7 3002 9
8 3002 10
9 3003 85
10 3004 1
After insert into Table B (the records randomly mixed up):
ID Postcode Total
1 3001 10
2 3002 20
3 3000 5
4 3003 85
5 3002 6
6 3001 6
7 3002 9
8 3000 20
9 3000 10
10 3004 1
Yes you can:
INSERT INTO TableB
SELECT *
FROM (SELECT TOP 10 * FROM TableA ORDER BY NEWID()) AS tmp
Make sure TableB does not have a clustered key or else it won't work. Change TOP 10 to the number of rows you have in TableA.
Edit: a commenter pointed that the original version won't work in SQL Server 2012 and above. In that case you need a more heavy handed version (updated).

Access SQL - Select only the last sequence

I have a table with an ID and multiple informative columns. Sometimes however, I can have multiple data for an ID, so I added a column called "Sequence". Here is a shortened example:
ID Sequence Name Tel Date Amount
124 1 Bob 873-4356 2001-02-03 10
124 2 Bob 873-4356 2002-03-12 7
124 3 Bob 873-4351 2006-07-08 24
125 1 John 983-4568 2007-02-01 3
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
So, I would like to obtain only these lines:
124 3 Bob 873-4351 2006-07-08 24
125 2 John 983-4568 2008-02-08 13
126 1 Eric 345-9845 2010-01-01 18
Anyone could give me a hand on how I could build a SQL query to do this ?
Thanks !
You can calculate the maximum sequence using group by. Then you can use join to get only the maximum in the original data.
Assuming your table is called t:
select t.*
from t join
(select id, MAX(sequence) as maxs
from t
group by id
) tmax
on t.id = tmax.id and
t.sequence = tmax.maxs