查询日期范围之间的帮助,但不是最近的

时间:2015-10-12 16:34:21

标签: mysql

我知道这可以写成一个单独的SQL语句,但我不知道该怎么做。我有两个单独的查询。这可以从去年的特定时期获取所有订单

SELECT * FROM `order` WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now() ORDER BY date_added ASC

和一个从上个月开始的

unit LVFix;

interface

uses
  Winapi.Windows, Winapi.Messages, System.Classes, System.UITypes, 
  Vcl.Controls, Vcl.ComCtrls;

type
  TListView = class(Vcl.ComCtrls.TListView)
  strict private
    type
    TColumnRec = record
      Alignment: TAlignment;
      AutoSize: Boolean;
      Caption: String;
      ImageIndex: TImageIndex;
      MaxWidth, MinWidth, Width: TWidth;
      Tag: Integer;
      ID: Integer;
    end;
    var
      FSavedCols: TArray<TColumnRec>;
      FSavedColOrder: TArray<Integer>;
  private
    procedure SaveColumnState;
    procedure RestoreColumnState;
  protected
    procedure CMRecreate(var M: TMessage); message CM_RECREATEWND;
  end;

implementation

uses
  Winapi.CommCtrl;

{ TListView }

procedure TListView.CMRecreate(var M: TMessage);
begin
  SaveColumnState;
  inherited;
  RestoreColumnState;
end;

procedure TListView.RestoreColumnState;
var
  I: Integer;
begin
  Items.BeginUpdate; //lock to prevent unnecessary events firing
  try
    //recreate columns
    Columns.Clear;
    for I := 0 to High(FSavedCols) do
    begin
      with Columns.Add do
      begin
        Alignment := FSavedCols[I].Alignment;
        AutoSize := FSavedCols[I].AutoSize;
        Caption := FSavedCols[I].Caption;
        ImageIndex := FSavedCols[I].ImageIndex;
        MinWidth := FSavedCols[I].MinWidth;
        MaxWidth := FSavedCols[I].MaxWidth;
        Width := FSavedCols[I].Width;
        Tag := FSavedCols[I].Tag;
      end;
    end;
    //restore column order
    if Length(FSavedColOrder) <> 0 then
      ListView_SetColumnOrderArray(Handle, Columns.Count, PInteger(FSavedColOrder));
  finally
    Items.EndUpdate;
  end;
end;

procedure TListView.SaveColumnState;
var
  R: LongBool;
  I: Integer;
  J: Integer;
  T: TColumnRec;
begin
  //save column order
  SetLength(FSavedColOrder, Columns.Count);
  R := ListView_GetColumnOrderArray(Handle, Columns.Count, PInteger(FSavedColOrder));
  if not R then
    SetLength(FSavedColOrder, 0);
  //save original columns in original order
  SetLength(FSavedCols, Columns.Count);
  for I := 0 to Columns.Count - 1 do
  begin
    FSavedCols[I].Alignment := Columns[I].Alignment;
    FSavedCols[I].AutoSize := Columns[I].AutoSize;
    FSavedCols[I].Caption := Columns[I].Caption;
    FSavedCols[I].ImageIndex := Columns[I].ImageIndex;
    FSavedCols[I].MinWidth := Columns[I].MinWidth;
    FSavedCols[I].MaxWidth := Columns[I].MaxWidth;
    FSavedCols[I].Width := Columns[I].Width;
    FSavedCols[I].Tag := Columns[I].Tag;
    FSavedCols[I].ID := Columns[I].ID;
  end;
  for I := 0 to High(FSavedCols) - 1 do
    for J := I + 1 to High(FSavedCols) do
      if FSavedCols[J].ID < FSavedCols[I].ID then
      begin
        T := FSavedCols[I];
        FSavedCols[I] := FSavedCols[J];
        FSavedCols[J] := T;
      end;
end;

end.

我想要做的是现在加入这两个,这样我只得到去年在日期范围内的订单的customer_id(查询1),但是在上个月没有下订单(查询2)。

我知道有一种方法可以将其设置为连接,但我对sql join的了解不是很有限。谢谢你的帮助。

3 个答案:

答案 0 :(得分:1)

我通常会使用相关的not exists谓词,因为我觉得它与问题的意图很吻合:

SELECT * 
FROM `order` o1
WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
  AND NOT EXISTS (
    SELECT 1 
    FROM `order` o2
    WHERE date_added BETWEEN DATE_SUB(NOW(), INTERVAL 1 MONTH) AND NOW() 
      AND o1.customer_id = o2.customer_id
);

答案 1 :(得分:1)

http://sqlfiddle.com/#!9/35ed0/1

SELECT * FROM `order` 
WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
   AND customer_id NOT IN (
   SELECT DISTINCT customer_id  FROM `order` 
   WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now())

更新如果每个customer_id只需要1条记录,则此处为an example。从性能角度来看,这不是最好的。但它只返回每个客户的最后一个(根据date_added列)订单。

SELECT t.*,
   if(@fltr=customer_id, 0, 1) fltr,
   @fltr:=customer_id
FROM (SELECT *
  FROM `order` 
  WHERE date_added BETWEEN '2014-10-01' AND '2014-11-01'
    AND customer_id NOT IN (
     SELECT DISTINCT customer_id  FROM `order` 
     WHERE date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now())
  ORDER BY customer_id, date_added DESC
) t
HAVING (fltr=1);

答案 2 :(得分:0)

我喜欢使用group byhaving来解决这些问题。您正在寻找客户ID,所以:

select o.customer_id
from orders o
group by o.customer_id
having sum(date_added BETWEEN '2014-10-01' AND '2014-11-01') > 0 and
       sum(date_added BETWEEN DATE_SUB( now(), INTERVAL 1 MONTH) AND Now()) = 0;