2017-04-27 8 views
0

ich wie die folgenden eine Tabelle haben:Vergleichen Zeilen in Oracle-Tabelle und aktualisieren passende diejenigen

**ID  tDate  Product Price Quantity BuySell Status** 
    1  10-May-17  pppp  $12  20   Buy  Null 
    2  12-May-17  tttt  $10  20   Sell  Null 
    3  12-May-17  tttt  $10  20   Buy  Null 
    4  18-May-17  pppp  $14  20   Sell  Null 
    5  18-May-17  pppp  $14  20   Buy  Null 
    6  18-May-17  pppp  $14  20   Sell  Null 

Ich brauche das Feld mit dem Namen Status zu aktualisieren, und setzen Sie ihn auf ‚Matched‘, wo immer ein Paar gefunden wird mit gleichem tDate, Produkt, Preis und Quantität und NICHT gleich BuySell.

Es folgt das gewünschte Ergebnis:

**ID  tDate  Product Price Quantity BuySell Status** 
    1  10-May-17  pppp  $12  20   Buy  Null 
    2  12-May-17  tttt  $10  20   Sell  Matched 
    3  12-May-17  tttt  $10  20   Buy  Matched 
    4  18-May-17  pppp  $14  20   Sell  Matched 
    5  18-May-17  pppp  $14  20   Buy  Matched 
    6  18-May-17  pppp  $14  20   Sell  Null 

Hinweis Wie 6 # stimmen nicht überein, weil es nur mit einem anderen null mithalten können.

Ich hoffe, ich kann dies mit einer einzigen SQL-Anweisung ausführen.

Was ich gerade mache, ist wahrscheinlich der schlechteste Ansatz: Ich lade in Pandas Datenrahmen in Python, und dann durchlaufen ich jede Zeile, die sie vergleicht.

s = "SELECT ID, Account, product, Price, tDate, BuySell, Qty" + \ 
    "FROM Table " + \ 
    "WHERE Status IS NULL " + \ 
    "ORDER BY Account, product, tDate, Price, Qty" 

df = pd.read_sql(s, conn) 

for i in range(len(df.index)-1): 

    if df.iloc[i, 1] == df.iloc[i+1, 1] \ 
     and df.iloc[i, 2] == df.iloc[i+1, 2] \ 
     and df.iloc[i, 3] == df.iloc[i+1, 3] \ 
     and df.iloc[i, 4] == df.iloc[i+1, 4] \ 
     and df.iloc[i, 5] != df.iloc[i+1, 5] \ 
     and df.iloc[i, 6] == df.iloc[i+1, 6]: 

     s = "UPDATE Temp_Fees " + \ 
      "SET Strategy = 'UNALLOCATED \ CANCELLED' " + \ 
      "WHERE ID = " + str(df.iloc[i,0]) + \ 
      " OR ID = " + str(df.iloc[i + 1, 0]) 

     #custom function that will execute and commit statement 
     bb.EXECUTE(s) 

     #avoid reading a matched row 
     i = i + 1 

Danke

+1

kann es pro Tag mehr als ein Paar von Buy-Sell sein? –

+1

@vkp Ja, es ist sogar in dem Beispiel (Datensätze 4, 5, 6). Edit: Ich gebe zu, das Beispiel zeigt nicht explizit, dass es mehr als ein Match pro Tag geben kann, aber zusammen mit der Beschreibung "# 6 stimmt nicht überein, weil es nur mit einer anderen Null übereinstimmen kann", sagt es implizit. –

+0

Bearbeiten Sie die Frage und erklären Sie, was zu tun ist, wenn Duplikate zwischen den Schlüsseln vorhanden sind. –

Antwort

2

Ungeprüfte aber so etwas wie dies nur mit SQL:

MERGE INTO your_table dst 
USING (
    SELECT ROW_NUMBER() OVER (
      PARTITION BY tDate, Product, Price, Quantity, BuySell 
      ORDER BY ID 
      ) AS idx, 
     COUNT(CASE BuySell WHEN 'Buy' THEN 1 END) OVER (
      PARTITION BY tDate, Product, Price, Quantity 
      ) AS num_buy, 
     COUNT(CASE BuySell WHEN 'Sell' THEN 1 END) OVER (
      PARTITION BY tDate, Product, Price, Quantity 
      ) AS num_sell 
    FROM your_table 
) src 
ON (src.ROWID = dst.ROWID AND src.idx <= LEAST(src.num_buy, src.num_sell)) 
WHEN MATCHED THEN 
    UPDATE SET Status = 'Matched'; 
+0

Danke! Ich habe es getestet, aber etwas stimmt nicht. Es gibt viel zu viele Zeilen, die übereinstimmen, ohne eine Zeile mit gleichen Daten, Preis, Menge und Produkt zu haben. – Kelaref

+0

@Kelaref Innerhalb der ersten 5 Minuten habe ich eine kleine Änderung vorgenommen, bei der eine Instanz von "Buy" zu "Sell" in der zweiten "COUNT" -Anweisung geändert wurde. Hast du es auf der ursprünglichen oder der aktuellen Version getestet? – MT0

+0

Das ist schön. Würde es Ihnen etwas ausmachen zu erklären, wie es funktioniert? Das ist mir so fremd. – Kelaref

1

Sie können die Zahl der Buy-Sell-Paare pro TDate und Aktualisierung solcher Reihen zu bekommen.

MERGE INTO tablename dst 
USING (select t.*,count(*) over(partition by tDate,Product,Price,Quantity,rn) as cnt 
     from (select t.*,row_number() over(partition by tDate,Product,Price,Quantity,buysell order by id) as rn 
      from tablename t) t 
     ) src 
ON (src.id = dst.id AND src.cnt=2) 
WHEN MATCHED THEN 
UPDATE SET Status = 'Matched'; 

Führen Sie diese Abfrage aus, um zu sehen, wie Zeilennummern dem Kauf-Verkauf zugeordnet werden.

select t.*,count(*) over(partition by tDate,Product,Price,Quantity,rn) as cnt 
from (select t.*,row_number() over(partition by tDate,Product,Price,Quantity,buysell order by id) as rn 
     from tablename t) t 
1

Hier ist eine andere Perspektive zu den anderen hinzufügen. Dies adressiert nur den übereinstimmenden Teil und nicht den Aktualisierungs- oder Zusammenführungsteil. Ich hatte kürzlich ein ähnliches Problem, bei dem ich Datensätze suchen musste, die nach Datum und Ort der Transaktion übereinstimmten, aber aus zwei verschiedenen Quellen stammten. In diesem Fall müssen die Datensätze bereits sortiert sein, damit die gleichen Datensätze zusammenkommen. Die innere Abfrage vergleicht den Datensatz mit dem vorherigen und dem nachfolgenden und erfasst sie, wenn sie übereinstimmen. Dann bestimmt die äußere Abfrage, ob sie die "Differenz" -Kriterien erfüllen. Hoffe das hilft.

select sbs.trnsid, sbs.amount, sbs.transaction_date, sbs.posted_date, sbs.srcid, 
     sbs.credited_flag, sbs.accid, sbs.compid, sbs.badgeid, sbs.locid, sbs.date_credited, 
     sbs.searchable, sbs.priortime, sbs.nexttime, sbs.priorsource, sbs.nextsource 
    from 
    (select trnsid, amount, transaction_date, posted_date, srcid, credited_flag, 
     accid, compid, badgeid, locid, date_credited, transaction_date||locid as searchable, 
     lag(transaction_date||locid, 1) over (order by accid) as priortime, 
     lead(transaction_date||locid, 1) over (order by accid) as nexttime, 
    lag(srcid, 1) over (order by accid) as priorsource, 
    lead(srcid, 1) over (order by accid) as nextsource 
    from transactions_table 
    where accid = v_acct 
     and transaction_date >= to_date('10/01/2016 00:00:00', 'mm/dd/yyyy hh24:mi:ss') 
     and transaction_date <= to_date('04/23/2017 23:59:59', 'mm/dd/yyyy hh24:mi:ss') 
     and srcid in ('B', 'S') order by accid, transaction_date, locid) sbs 
    where (sbs.searchable = sbs.nexttime and sbs.srcid = 'S' and sbs.nextsource = 'B') 
    or (sbs.searchable = sbs.priortime and sbs.srcid = 'B' and sbs.priorsource = 'S'); 
1
merge into mytable t3 
using (select t1.*, count(*) over (partition by tdate,product,price,quantity,field) as field2 from 
(
select mytable.*, row_number() over (partition by mytable.tdate,mytable.product,mytable.price,mytable.quantity,mytable.buysell 
order by id) field from 
mytable) t1) t2 
on (t2.id=t3.id and t2.field2='2') 
when matched then 
update set status='Matched'; 
Verwandte Themen