2

次の表を検討してくださいdaterange

_date        trading_day
------------------------
2011-08-01   1
2011-07-31   0
2011-07-30   0
2011-07-29   1
2011-07-28   1
2011-07-27   1
2011-07-26   1
2011-07-25   1
2011-07-24   0
2011-07-23   0
2011-07-22   1
2011-07-21   1
2011-07-20   1
2011-07-19   1
2011-07-18   1
2011-07-17   0

指定された_dateの数日前に_dateを返すクエリが必要です。xカウントバックするときは、_dayswithtrading_day = 0は無視する必要があります。いくつかの例:

input                    | output
-------------------------+------------
1 day  before 2011-07-19 | 2011-07-18
2 days before 2011-08-01 | 2011-07-28 (trading_day = 0 don't count)
3 days before 2011-07-29 | 2001-07-26

最初のものは簡単です:

SELECT _date 
FROM daterange 
WHERE trading_day = 0 AND _date < '2011-07-19' LIMIT 1

しかし、他の例を照会する方法がわかりません。あなたは?私はすべての場合に機能するソリューションを好むので、phpで日数を逆方向に可変にすることができます。

4

5 に答える 5

3

クエリ 1

SELECT `_date`
FROM `daterange` 
WHERE `trading_day` = '1' AND `_date` <= '2011-07-19' 
ORDER BY `_date` DESC 
LIMIT 1 
OFFSET 1;

クエリ 2

SELECT `_date` 
FROM `daterange` 
WHERE `trading_day` = '1' AND `_date` <= '2011-08-01' 
ORDER BY `_date` DESC 
LIMIT 1 
OFFSET 2;

クエリ 3

SELECT `_date`
FROM `daterange` 
WHERE `trading_day` = '1' AND `_date` <= '2011-07-29' 
ORDER BY `_date` DESC 
LIMIT 1 
OFFSET 3;

プリペアド ステートメント (PDO の例)

$stmt = $dbh->prepare("SELECT `_date`
    FROM `daterange` 
    WHERE `trading_day` = '1' AND `_date` <= :given_date
    ORDER BY `_date` DESC 
    LIMIT 1 
    OFFSET :days_before");
$stmt->bindParam(':given_date', $given_date);
$stmt->bindParam(':days_before', $days_before);
$stmt->execute();
于 2012-08-30T15:43:20.153 に答える
1

最初の例は、今のところ偶然にしか機能しません:)結果セットに順序を適用して、任意の日付だけでなく、2011-07-19 より前の最大の日付を確実に取得する必要があります。

SELECT _date
FROM daterange
WHERE trading_day <> 0 AND _date < '2011-07-19'
ORDER BY _date DESC
LIMIT 1

特定の日の前の最初の日ではなく、他の日が必要な場合は、クエリにも OFFSET を適用します。

これは、#3に必要なものを提供します:

SELECT _date
FROM daterange
WHERE trading_day <> 0 AND _date < '2011-07-29'
ORDER BY _date DESC

LIMIT 1
OFFSET 2

OFFSET 2、返される最初の 2 つの結果をスキップし、3 番目の結果から開始するように MySQL に指示します。

于 2012-08-30T15:46:02.760 に答える
1

ご質問の内容がよくわかりませんが、前回の取引日と、それが何日前かを選択したいようです。テーブル内のすべての日付に対してそれを行うのか、それとも単一の日付に対して行うのかはわかりません。

それ以外の場合は非常に単純なクエリであるため、テーブル内のすべての日付用であると想定します。

SELECT 
dr._date as the_date, 
d2._date as previous_trading_date, 
DATEDIFF(dr._date, d2._date) days_ago

FROM daterange dr
JOIN (
    SELECT _date FROM daterange
    WHERE trading_day > 0
    ORDER BY _date DESC
) d2 ON d2._date < dr._date

GROUP BY dr._date
ORDER BY dr._date DESC

このクエリが行うことは、daterange からすべての日付を選択し、サブクエリを実行して、取引日ではない日付を除いたすべての日付を選択し、それらを降順 (最新順) に並べ替えることです。すべての日付をその前のすべての日付に結合しますがdaterange._date、最初の行のみを取得するためにグループ化します (注文でサブ選択を行ったため、これは取引日の最初の日付になります)。句)。次に、DATEDIFF()関数を使用して、日付と前の取引日の間の日数をカウントします。


したがって、$x特定の日付 ( ) より前の日数 ( ) の前の日付を選択し、値が の$date日付を無視する場合は、次のようにします。trading_day0

SELECT _date

FROM daterange

WHERE _date < '{$date}'
AND trading_day > 0

ORDER BY _date DESC
LIMIT 1
OFFSET {$x - 1}

この句を使用すると、句に一致するOFFSET最初の日をスキップできます。これは、希望する日に到着するはずです。ただし、このクエリにはいくつかの仮定があります。主に、毎日 1 行 (そして 1 行のみ) をオンにします。そうしないと、予期しない結果が生じる可能性があります。 {$x - 1}WHEREdaterange

しかし、それについて考えた後、次のようなクエリを実行できます。

SELECT _date

FROM daterange

WHERE _date <= DATE_SUB('2011-08-01', INTERVAL {$x} DAY)
AND trading_day > 0

ORDER BY _date DESC
LIMIT 1

このクエリは日付減算を行うため、数日前の日付に戻りますが、句{$x}を追加することでtrading_day > 0、取引日ではない日を削除し、結果を降順で並べ替え、最初の日付を選択します。 -それはあなたが望む日付でなければなりません。やってみて。

于 2012-08-30T15:59:47.707 に答える
1
SELECT DATE(_date - INTERVAL trading_day DAY) FROM daterange;

このクエリは、取引日が 0 の場合は無視し、日付をそのまま返します。取引日がない日付を除外する場合は、次のようにします。

SELECT DATE(_date - INTERVAL trading_day DAY) FROM daterange WHERE trading_day!=0;

また、日付フィールドがすでに 2012-01-01 の形式である場合、ここで DATE() は必要ありません。日付フィールドがタイムスタンプ (2012-01-01 10:01:17) の場合、DATE() は日付部分のみを返すため、(2012-01-01) のようになります。言い換えれば、これはあなたが提示したものに基づいて同様に機能します:

SELECT _date - INTERVAL trading_day DAY FROM daterange;

そしてそれに応じて

SELECT _date - INTERVAL trading_day DAY FROM daterange WHERE trading_day!=0;
于 2012-08-30T15:42:39.140 に答える
0
Select temp._date 
FROM (Select _date FROM daterange WHERE trading_day<>0 AND trading_day < $date ORDER BY _date) as temp
ORDER BY _date LIMIT $days_before;

そして、最初のレコードのみを取得します。

将来的には、ORDER BYをDESCに変更し、同封のselectのwhere句を変更することもできます。

于 2012-08-30T15:50:56.217 に答える