To pair up records in oracle sql - sql

This is my sql:
when executed, it said
00000 - "missing keyword" on the position of "CROSS APPLY".
I'm just trying to pair up some records (in one day =20160720) with same TICKET_ID in the table and return their T_TIME and T_LOCATION.
select a.T_TIME, b.T_TIME, a.T_LOCATION, b.T_LOCATION
FROM TABLE a
CROSS APPLY
(select * from TABLE b where a.TICKET_ID = b.TICKET_ID having count(TICKET_ID) > 1) b
where (a.T_DATE=20160720);
Is the problem caused by using CROSS APPLY?
Ok, here is the problem I originally want to solve :)
The table looks like this:
T_TIME |T_LOCATION | TICKET_ID|T_DATE
20160720091032| ---0103| 1A268F|20160720
20160720095842| ---0115| 63T37H|20160720
20160720133408| ---0124| 1A268F|20160720
20160721152400| ---0116| 598I3R|20160721
20160720125844| ---0147| 63T37H|20160720
I want to pair up the records with same TICKET_ID. 2 records share one same TICKET_ID. And I want the output like:
20160720091032|20160720133408|0103|0124|
20160720095842|20160720125844|0115|0147|
The table is very large like for T_DATE=20160720 there will be 200000 records in total.

One way of doing it would be:
select a.ticket_id, a.t_time, b.t_time, a.t_location, b.t_location
from the_table a
join the_table b on a.ticket_id = b.ticket_id and a.t_time < b.t_time
where a.t_date = 20160720;
The join condition and a.t_time < b.t_time ensure that the "other" version of a pair isn't in the result e.g. you only get (0103, 0124) but not (0124, 0103).

Related

SQL - Returning fields based on where clause then joining same table to return max value?

I have a table named Ticket Numbers, which (for this example) contain the columns:
Ticket_Number
Assigned_Group
Assigned_Group_Sequence_No
Reported_Date
Each ticket number could contain 4 rows, depending on how many times the ticket changed assigned groups. Some of these rows could contain an assigned group of "Desktop Support," but some may not. Here is an example:
Example of raw data
What I am trying to accomplish is to get the an output that contains any ticket numbers that contain 'Desktop Support', but also the assigned group of the max sequence number. Here is what I am trying to accomplish with SQL:
Queried Data
I'm trying to use SQL with the following query but have no clue what I'm doing wrong:
select ih.incident_number,ih.assigned_group, incident_history2.maxseq, incident_history2.assigned_group
from incident_history_public as ih
left join
(
select max(assigned_group_seq_no) maxseq, incident_number, assigned_group
from incident_history_public
group by incident_number, assigned_group
) incident_history2
on ih.incident_number = incident_history2.incident_number
and ih.assigned_group_seq_no = incident_history2.maxseq
where ih.ASSIGNED_GROUP LIKE '%DS%'
Does anyone know what I am doing wrong?
You might want to create a proper alias for incident_history. e.g.
from incident_history as incident_history1
and
on incident_history1.ticket_number = incident_history2.ticket_number
and incident_history1.assigned_group_seq_no = incident_history2.maxseq
In my humble opinion a first error could be that I don't see any column named "incident_history2.assigned_group".
I would try to use common table expression, to get only ticket number that contains "Desktop_support":
WITH desktop as (
SELECT distinct Ticket_Number
FROM incident_history
WHERE Assigned_Group = "Desktop Support"
),
Than an Inner Join of the result with your inner table to get ticket number and maxSeq, so in a second moment you can get also the "MAXGroup":
WITH tmp AS (
SELECT i2.Ticket_Number, i2.maxseq
FROM desktop D inner join
(SELECT Ticket_number, max(assigned_group_seq_no) as maxseq
FROM incident_history
GROUP BY ticket_number) as i2
ON D.Ticket_Number = i2.Ticket_Number
)
SELECT i.Ticket_Number, i.Assigned_Group as MAX_Group, T.maxseq, i.Reported_Date
FROM tmp T inner join incident_history i
ON T.Ticket_Number = i.Ticket_Number and i.assigned_group_seq_no = T.maxseq
I think there are several different method to resolve this question, but I really hope it's helpful for you!
For more information about Common Table Expression: https://www.essentialsql.com/introduction-common-table-expressions-ctes/

SQL Math Operation In Correlated Subquery

I am working with three tables, basically, one is a bill of materials, one contains part inventory, and the last one contains work orders or jobs. I am trying to find out if it is possible to have a correlated subquery that can perform a math operation using a value from the outer query. Here's an example of what I'm trying to do:
SELECT A.work_order,A.assembly,A.job_quantity,
(SELECT COUNT(X.part_number)
FROM bom X
WHERE X.assembly = A.assembly
AND (X.quantity_required * A.job_quantity) >= (SELECT Y.quantity_available FROM inventory Y WHERE
Y.part_number = X.part_number)) AS negatives
FROM work_orders A
ORDER BY A.assembly ASC
I am attempting to find out, for a given work order, if there are parts that we do not have enough of to build the assembly. I'm currently getting an "Error correlating fields" error. Is it possible to do this kind of operation in a single query?
Try moving the subquery to a join, something like this:
SELECT a.work_order, a.assembly, a.job_quantity, n.negatives
FROM work_orders a JOIN (SELECT x.part_number, COUNT(x.part_number) as negatives
FROM bom x JOIN work_orders b
ON x.assembly = b.assembly
WHERE (x.quantity_required * b.job_quantity) >= (SELECT y.quantity_available
FROM inventory y WHERE
y.part_number = x.part_number)
GROUP BY x.part_number) n
ON a.part_number = n.part_number
ORDER BY a.assembly ASC
Or create a temporary cursor with the subquery and then use it to join the main table.
Hope this helps.
Luis

Left/Right join table with itself

I have a table which contains all the active loans for every month (for example 2017_01, 2017_02, 2017_03, etc). As I don't have another table which contains the Non Active loans (the closed ones) I have to manipulate the same table to get the closed loans for every specific months.
I have tried RIGHT OUTER JOIN in order to get the loans which are part of the previous YEAR_MONTH and have a NULL value in the next month, but as the table is joining itself using the LOAN_NUMBER field as a key, I am not getting the desired results.
Any idea of what I can do?
Ps: In other cases I needed to do that I used the "WHERE NOT EXISTS" clause, but I had two different tables.
My query is:
SELECT DM07MD.LOAN_NUMBER, DM07MD2.LOAN_NUMBER AS L2
FROM [dbo].[DM_07MONTHLY_DATA] DM07MD
LEFT OUTER JOIN [dbo].[DM_07MONTHLY_DATA] DM07MD2
ON DM07MD.LOAN_NUMBER = DM07MD2.LOAN_NUMBER
AND DM07MD.YYYY_MM = '2017_01'
WHERE DM07MD.S90T01_CLIENT_SEGMENT IN ('PI', 'MICRO')
AND DM07MD.S90T01_IS_RESTRUCTURED = 1
AND DM07MD2.LOAN_NUMBER IS NULL
AND DM07MD.YYYY_MM = '2017_02'
You can get the same by using exists,
SELECT DM07MD.LOAN_NUMBER FROM [dbo].[DM_07MONTHLY_DATA] DM07MD where DM07MD.YYYY_MM = '2017_02' and not exists
( SELECT 1 FROM [dbo].[DM_07MONTHLY_DATA] DM07MD2 where DM07MD.YYYY_MM = '2017_01' and DM07MD.LOAN_NUMBER=DM07MD2.LOAN_NUMBER )

SQL, Search by Date and not exists

I have two tables and need to search for all entries that exist in one table in another table by idProduct, only if the date (dateStamp) is less than or older than 7 days.
Because the api I'm using is restricted to only processing 3000 results at a time, the application will close and the next time I run the application I only want the idProducts that are say 3000 or greater for that idProduct, this will be run numerous times for the Suppliercode wll most likely already exist in the table.
So I've been looking at the not exists and getdate functions in sql but not been able to get the desired results.
SELECT
*
FROM
products
WHERE
(active = - 1)
AND suppliercode = 'TIT'
and (NOT EXISTS
(SELECT
idProduct
FROM compare
WHERE
(products.idProduct = idProduct)
OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE()))))
Any pointers would be great, I've changed the OR to AND but it doesn't seem to bring back the correct results.
I am guessing you want to match the rows in the two tables by idProduct as right now your inner query (NOT EXISTS (SELECT idProduct FROM compare WHERE (products.idProduct = idProduct) OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE())))) looks like it is finding all rows that don't match. As your subquery finds all rows that match or where the date is older than 7 days and makes sure that they don't exist.
Is this what your want?
SELECT *
FROM products as p
LEFT JOIN compare as c
ON p.idProduct = c.idProduct
WHERE p.active = -1 and p.suppliercode = 'TIT' and c.dateStamp < DATEADD(DAY,-7,GETDATE())
Have you tried this one yet?
SELECT * FROM products
WHERE (active = - 1) AND
suppliercode = 'TIT'
and ipProduct NOT IN
(
SELECT idProduct FROM compare
WHERE
(products.idProduct = idProduct) OR
(compare.dateStamp < DATEADD(DAY,-7,GETDATE()))
)
Try NOT IN instead:
...
and ProductId NOT IN
(SELECT
idProduct
FROM compare
WHERE
(products.idProduct = idProduct)
OR (compare.dateStamp < DATEADD(DAY,-7,GETDATE()))))
....

outer query to list only if its rowcount equates to inner subquery

Need help on a query using sql server 2005
I am having two tables
code
chargecode
chargeid
orgid
entry
chargeid
itemNo
rate
I need to list all the chargeids in entry table if it contains multiple entries having different chargeids
which got listed in code table having the same charge code.
data :
code
100,1,100
100,2,100
100,3,100
101,11,100
101,12,100
entry
1,x1,1
1,x2,2
2,x3,2
11,x4,1
11,x5,1
using the above data , it query should list chargeids 1 and 2 and not 11.
I got the way to know how many rows in entry satisfies the criteria, but m failing to get the chargeids
select count (distinct chargeId)
from entry where chargeid in (select chargeid from code where chargecode = (SELECT A.chargecode
from code as A join code as B
ON A.chargecode = B.chargeCode and A.chargetype = B.chargetype and A.orgId = B.orgId AND A.CHARGEID = b.CHARGEid
group by A.chargecode,A.orgid
having count(A.chargecode) > 1)
)
First off: I apologise for my completely inaccurate original answer.
The solution to your problem is a self-join. Self-joins are used when you want to select more than one row from the same table. In our case we want to select two charge IDs that have the same charge code:
SELECT DISTINCT c1.chargeid, c2.chargeid FROM code c1
JOIN code c2 ON c1.chargeid != c2.chargeid AND c1.chargecode = c2.chargecode
JOIN entry e1 ON e1.chargeid = c1.chargeid
JOIN entry e2 ON e2.chargeid = c2.chargeid
WHERE c1.chargeid < c2.chargeid
Explanation of this:
First we pick any two charge IDs from 'code'. The DISTINCT avoids duplicates. We make sure they're two different IDs and that they map to the same chargecode.
Then we join on 'entry' (twice) to make sure they both appear in the entry table.
This approach gives (for your example) the pairs (1,2) and (2,1). So we also insist on an ordering; this cuts to result set down to just (1,2), as you described.