2012-05-21 11 views
5

Mam tabeli, która zawiera transakcje magazynie:zapytań SQL, aby pokazać zmiany w kolumnie „Ogółem”

+------+----------------------+------------------+ 
| Item | Running Stock Total | Transaction Time | 
+------+----------------------+------------------+ 
| foo | 4     | 2012-05-12 11:07 | 
| bar | 3     | 2012-05-12 10:42 | 
| bar | 3     | 2012-05-12 9:42 | 
| bar | 2     | 2012-05-11 15:42 | 
| foo | 3     | 2012-05-11 10:02 | 
| bar | 3     | 2012-05-10 13:44 | 
...etc... 
+------+----------------------+------------------+ 

tj każdym razem coś się dzieje na magazynie, rząd jest tworzony w tej Tabeli-może to oznaczać akcji poziom rośnie (nowe zapasy), w dół (sprzedawane) lub pozostaje bez zmian (przesunięcie akcji).

Potrzebuję utworzyć kwerendę sql, która zwraca tylko wiersze, w których poziom zapasów rzeczywiście zmienił się dla określonej części i musi pokazywać zmiany w kolumnie "zapas" i "zapas".

tj 1 Item='bar'

+------+-----------+------------+----------------------+------------------+ 
| Item | Stock Up | Stock Down | Running Stock Total | Transaction Time | 
+------+-----------+------------+----------------------+------------------+ 
| bar |  1 |  0  | 3     | 2012-05-12 9:42 | 
| bar |  0 |  1  | 2     | 2012-05-11 15:42 | 
| bar |  1 |  0  | 3     | 2012-05-10 13:44 | 
+------+-----------+------------+----------------------+------------------+ 

e.g.2 Item='foo'

+------+-----------+------------+----------------------+------------------+ 
| Item | Stock Up | Stock Down | Running Stock Total | Transaction Time | 
+------+-----------+------------+----------------------+------------------+ 
| foo |  1 |  0  | 4     | 2012-05-12 11:07 | 
| foo |  2 |  0  | 3     | 2012-05-11 10:02 | 
+------+-----------+------------+----------------------+------------------+ 

Więc coś ...

SELECT 
    Item, {xyz} as 'Stock Up', {abc} as 'Stock Down', `Running Stock Total`, `Transaction Time` 
FROM 
    `StockTransactions` 
WHERE 
    `Item`='foo' 
HAVING 
    ('Stock Up'>0 or 'Stock Down'>0) 

można to zrobić?

+0

Jak rozróżniasz, kiedy wzrosły zapasy i kiedy spadły zapasy? – JHS

+0

Używając "Running Stock Total" – Urbycoz

+0

Twoja składnia wygląda jak SQL Server, ale twoje pytanie jest oznaczone jako MySQL. Którego używasz? – eggyal

Odpowiedz

3
SELECT `Item`, 
     `Stock Up`, 
     `Stock Down`, 
     `Running Stock Total`, 
     `Transaction Time` 

FROM (
    SELECT `Item`, 
      GREATEST(`Running Stock Total` - @`last_total`, 0) AS `Stock Up`, 
      GREATEST(@`last_total` - `Running Stock Total`, 0) AS `Stock Down`, 
      `Running Stock Total`, 
      `Transaction Time`, 
      @`last_total` := `Running Stock Total` 
    FROM  `StockTransactions` JOIN (SELECT @`last_total` := 0) AS lt 
    WHERE `Item` = 'bar' 
    ORDER BY `Transaction Time` ASC 
) AS t 

ORDER BY `Transaction Time` DESC 

Zobacz na sqlfiddle. Zapytanie zewnętrzne można oczywiście pominąć, jeśli chcesz, aby wyniki były uporządkowane w kolejności rosnącej według czasu transakcji oraz w dodatkowej kolumnie last_total.

+1

Zewnętrznej kwerendy nie można pominąć, ponieważ w zapytaniu zewnętrznym wiersze mogą (i muszą) być filtrowane przy warunku "Upgrade"> 0 lub "Stock Down"> 0 "(co jest wymagane przez pytanie a którego nie robisz). Poza tym, myślę, że twoje rozwiązanie powinno działać. –

+0

@eggyal To doskonałe i eleganckie rozwiązanie. Dziękuję Ci! – Urbycoz

+0

@AndriyM: Dobra uwaga - przeoczyłem ten wymóg. – eggyal

0

Jednym z rozwiązań może być:

  1. Zrób kursora, aby wybrać każdy wiersz naraz
  2. Sprawdź, czy wartość zmieniła się, a jeśli tak, włóż informacje w tabeli #temp
  3. Wybierz wszystko dane z tabeli #temp

Zamiast kursora można użyć krótkiego cyklu, jeśli można zidentyfikować sekwencyjnie wszystkie wiersze.

0

Chciałbym spróbować czegoś takiego jak ustawienie zmiennej, która zawiera dawną cenę akcji. Najpierw posortuj tabelę według pozycji, aby móc samodzielnie zająć się wszystkimi danymi dla każdego zasobu.

Następnie można powiedzieć coś w rodzaju: int counter = 0; decimal startingPrice = 0; koszt dziesiętny = 0;

 var list = new List<Decimal>(); 
     Decimal[] positivePercentagesToTest = new Decimal[] { 1.02m, 1.03m, 1.04m, 1.10m, 100 }; 
     Decimal[] negativePercentagesToTest = new Decimal[] { 0.99m, 0.985m, 0.98m, 0.95m, 0.9m }; 

     for (int i = 0; i <= positivePercentagesToTest.Count() -1 ;i++) 
     { 
      foreach (var s in stocks) 
      { 
       //if(s.Ticker == "BAC") 
       { 
        if (counter == 0) 
        { 
         startingPrice = s.Open; 
        } 
        counter++; 

        var openPrice = s.Open; 

        if (openPrice > (startingPrice * positivePercentagesToTest[i]) || openPrice < (startingPrice * negativePercentagesToTest[i])) 
        { 
         //sell 
         //same as percentage gain 
         var percentage = openPrice/startingPrice - 1; 

         list.Add(Math.Round(percentage, 2)); 
         counter = 0; 
        } 

       } 

      } 

      var amount = list.Sum(); 
      var profitToAdd = new Profits(); 
      profitToAdd.Amount = amount; 

To jest kod C#. Jeśli potrzebujesz go w sql, daj mi znać. To tylko logika, której bym użył.

+0

Obawiam się, że potrzebuję tego w sql. – Urbycoz

0

Nie znam twojego kodu SQL, ale w Oracle są funkcje analityczne, które umożliwiają dostęp do wartości kolumn z poprzedniego lub następnego wiersza w zestawie wyników. Możesz użyć wartości LAG(), aby zobaczyć różnicę między poprzednim a bieżącym wynikiem i zdecydować, czy było ono w górę, czy w dół. Czy jest coś podobnego w twoim SQL?

+0

Używam MySQL. Nie myśl, że ma coś podobnego. – Urbycoz

1

Moje rozwiązanie działa w oparciu o założenie, że Transaction Time jest unikalne na Item.

jestem symulowanie row_number() funkcji analitycznych za pośrednictwem widzenia pomocnika że tworzę:

CREATE VIEW running_stock AS 
SELECT s.item,s.running_total,s.transaction_dt, 
    (SELECT count(*) FROM stock WHERE item=s.item 
     AND transaction_dt <= s.transaction_dt) AS row_number 
    FROM stock s 
ORDER BY 1, 4; 

Po widok jest na swoim miejscu, można uzyskać pożądane rezultaty następujące zapytanie:

SELECT c.item AS "Item", 
    greatest(c.running_total - p.running_total, 0) AS "Stock Up", 
    greatest(p.running_total - c.running_total, 0) AS "Stock Down", 
    c.running_total AS "Running Total", 
    c.transaction_dt AS "Transaction Time" 
FROM running_stock c 
LEFT JOIN running_stock p ON c.item = p.item 
     AND p.row_number + 1 = c.row_number 
WHERE c.row_number > 1 
ORDER BY 1, 5; 

Ty może grać z tym zapytaniem na SQL Fiddle.

Powiązane problemy