我知道这可以写成一个单独的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的了解不是很有限。谢谢你的帮助。
答案 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 by
和having
来解决这些问题。您正在寻找客户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;