四个表的 SQLite 复杂连接查询
SQLite Complex Join Query for four tables
我创建了以下四个表:
CREATE TABLE "Customer" (
"Customer_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"First_Name" TEXT NOT NULL,
"Last_Name" TEXT NOT NULL,
"Street_Address" TEXT NOT NULL,
"Apartment_Number" TEXT NOT NULL,
"City" TEXT NOT NULL,
"State" TEXT NOT NULL,
"ZIP" INTEGER NOT NULL,
"Home_Phone" INTEGER NOT NULL,
"Mobile_Phone" INTEGER NOT NULL,
"Other_Phone" INTEGER NOT NULL
);
CREATE TABLE "Donut" (
"Donut_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NOT NULL,
"Description" TEXT NOT NULL,
"Unit_Price" FLOAT NOT NULL
);
CREATE TABLE "Donut_Order" (
"Donut_Order_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"Customer_ID" INTEGER REFERENCES "Customer" ("Customer_ID"),
"Order_Date" REAL NOT NULL,
"Notes" TEXT
);
CREATE TABLE "Order_Line_Item" (
"Donut" INTEGER NOT NULL REFERENCES "Donut" ("Donut_ID"),
"Donut_Order" INTEGER NOT NULL REFERENCES "Donut_Order"("Donut_Order_ID"),
"Qty" INTEGER NOT NULL,
PRIMARY KEY ("Donut", "Donut_Order")
);
然后我插入了以下数据(为简洁起见被截断):
INSERT INTO Customer ( First_Name, Last_Name, Street_Address, Apartment_Number, City, State, ZIP, Home_Phone, Mobile_Phone, Other_Phone) VALUES('Alvin','Cressfol','1313 Mockingbird Lane','01','Auburn','AL','36801','+3345550480','3345550480','+3345555423');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Plain','Plain Donut','1.50');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Glazed','Glazed Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Cinnamon', 'Cinnamon Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Chocolate','Chocolate Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Sprinkle','Sprinkle Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Gluten-Free','Gluten-Free Donut','2.00');
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now')));
INSERT INTO Order_Line_Item VALUES(1,1,1);
INSERT INTO Order_Line_Item VALUES(1,2,12);
INSERT INTO Order_Line_Item VALUES(1,3,8);
INSERT INTO Order_Line_Item VALUES(1,4,8);
INSERT INTO Order_Line_Item VALUES(1,5,6);
INSERT INTO Order_Line_Item VALUES(1,6,6);
现在我需要复杂连接来为 Order_ID = 1 出现的每个 Order_Line_Item 输出一行。输出的格式需要与此类似:
Output Example
我尝试了以下代码,但它似乎不起作用:
SELECT I.Order_Date ,
ILI.Donut_Order_Number,
substr(C.First_Name," ",C.Last_Name) AS CUSTNAME,
C.Street_Address,
C.CITY,
C.ZIP,
C.Home_Phone,
C.Mobile_Phone,
C.Other_Phone,
C.Apartment_Number,
ILI.Quantity,
ILI.Donut_ID,
D.Name,
D.Description,
D.Unit_Price,
FROM CUSTOMER C
JOIN Donut_Order I ON C.Customer_ID=I.Customer_ID
JOIN Order_LINE_ITEM ILI ON I.Donut_Order_ID = 1
JOIN DONUT D ON ILI.Donut_ID=D.Donut_ID;
我的 SQLite 技能不是很好,而且我很难理解这一点。在此先感谢您的帮助。
我认为提到的语法错误是 ,
就在 FROM
之前
and/or substr()
.
的极其奇怪的用法
您还应该修复对不存在列的引用:
ILI.Donut_Order_Number
ILI.Quantity
ILI.Donut_ID
因此我建议使用下面的代码,并不是说它完成了你最终想要做的事情,但是语法错误和其他一些明显的错误都消失了。
SELECT
strftime("%m/%d/%Y %H:%M", I.Order_Date) as "Order Date",
ILI.Donut_Order,
C.First_Name||" "||C.Last_Name AS CUSTNAME,
C.Street_Address,
C.Apartment_Number,
C.CITY,
C."STATE",
C.ZIP,
C.Home_Phone,
C.Mobile_Phone,
C.Other_Phone,
ILI.Qty,
ILI.Donut,
D.Name,
D.Description,
D.Unit_Price
FROM CUSTOMER C
JOIN Donut_Order I USING (Customer_ID)
JOIN Order_LINE_ITEM ILI ON I.Donut_Order_ID = ILI.Donut_Order
JOIN DONUT D ON ILI.Donut = D.Donut_ID;
输出(.headers on
):
Order Date|Donut_Order|CUSTNAME|Street_Address|Apartment_Number|City|State|ZIP|Home_Phone|Mobile_Phone|Other_Phone|Qty|Donut|Name|Description|Unit_Price
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|1|1|Plain|Plain Donut|1.5
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|12|2|Glazed|Glazed Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|8|3|Cinnamon|Cinnamon Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|8|4|Chocolate|Chocolate Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|5|Sprinkle|Sprinkle Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|6|Gluten-Free|Gluten-Free Donut|2.0
04/18/2017 21:02|2|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|6|Gluten-Free|Gluten-Free Donut|2.0
请注意,为了使用上述代码获得良好结果,需要对样本数据进行以下两项更改。
我修复了示例数据,因为我认为 order_id 和 donut_id 被意外交换了。使用此代码:
-- fix sample input
delete from Order_Line_Item;
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(1,1,1);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(2,1,12);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(3,1,8);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(4,1,8);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(5,1,6);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(6,1,6);
我还添加了第二个订单,以便更好地测试深度:
-- prepare the use of two orders
delete from Donut_Order;
-- use two orders, for better testing
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now')));
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now', '+1 day')));
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(6,2,6);
除了所有语法错误外,Order_Line_Item
和 Donut_Order
表之间没有连接。因此,您将获得所有订单行项目的组合,即使是那些与您想要的订单不匹配的项目。
联接中的 ON 子句应仅用于实际的联接条件。要进一步过滤结果,您应该改用 WHERE(这使意思更清楚,并且您会更容易注意到缺少某些连接条件):
SELECT ...
FROM Customer C
JOIN Donut_Order I USING (Customer_ID)
JOIN Order_Line_Item ILI ON I.Donut_Order_ID = ILI.Donut_Order
JOIN Donut D ON ILI.Donut = D.Donut_ID
WHERE I.Donut_Order_ID = 1;
(如果保证匹配的列同名,可以使用更简单的USING子句,你的列不一致,有的用_ID
后缀,有的不用。)
我创建了以下四个表:
CREATE TABLE "Customer" (
"Customer_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"First_Name" TEXT NOT NULL,
"Last_Name" TEXT NOT NULL,
"Street_Address" TEXT NOT NULL,
"Apartment_Number" TEXT NOT NULL,
"City" TEXT NOT NULL,
"State" TEXT NOT NULL,
"ZIP" INTEGER NOT NULL,
"Home_Phone" INTEGER NOT NULL,
"Mobile_Phone" INTEGER NOT NULL,
"Other_Phone" INTEGER NOT NULL
);
CREATE TABLE "Donut" (
"Donut_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"Name" TEXT NOT NULL,
"Description" TEXT NOT NULL,
"Unit_Price" FLOAT NOT NULL
);
CREATE TABLE "Donut_Order" (
"Donut_Order_ID" INTEGER PRIMARY KEY AUTOINCREMENT,
"Customer_ID" INTEGER REFERENCES "Customer" ("Customer_ID"),
"Order_Date" REAL NOT NULL,
"Notes" TEXT
);
CREATE TABLE "Order_Line_Item" (
"Donut" INTEGER NOT NULL REFERENCES "Donut" ("Donut_ID"),
"Donut_Order" INTEGER NOT NULL REFERENCES "Donut_Order"("Donut_Order_ID"),
"Qty" INTEGER NOT NULL,
PRIMARY KEY ("Donut", "Donut_Order")
);
然后我插入了以下数据(为简洁起见被截断):
INSERT INTO Customer ( First_Name, Last_Name, Street_Address, Apartment_Number, City, State, ZIP, Home_Phone, Mobile_Phone, Other_Phone) VALUES('Alvin','Cressfol','1313 Mockingbird Lane','01','Auburn','AL','36801','+3345550480','3345550480','+3345555423');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Plain','Plain Donut','1.50');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Glazed','Glazed Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Cinnamon', 'Cinnamon Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Chocolate','Chocolate Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Sprinkle','Sprinkle Donut','1.75');
INSERT INTO DONUT(Name, Description, Unit_Price) VALUES('Gluten-Free','Gluten-Free Donut','2.00');
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now')));
INSERT INTO Order_Line_Item VALUES(1,1,1);
INSERT INTO Order_Line_Item VALUES(1,2,12);
INSERT INTO Order_Line_Item VALUES(1,3,8);
INSERT INTO Order_Line_Item VALUES(1,4,8);
INSERT INTO Order_Line_Item VALUES(1,5,6);
INSERT INTO Order_Line_Item VALUES(1,6,6);
现在我需要复杂连接来为 Order_ID = 1 出现的每个 Order_Line_Item 输出一行。输出的格式需要与此类似:
Output Example
我尝试了以下代码,但它似乎不起作用:
SELECT I.Order_Date ,
ILI.Donut_Order_Number,
substr(C.First_Name," ",C.Last_Name) AS CUSTNAME,
C.Street_Address,
C.CITY,
C.ZIP,
C.Home_Phone,
C.Mobile_Phone,
C.Other_Phone,
C.Apartment_Number,
ILI.Quantity,
ILI.Donut_ID,
D.Name,
D.Description,
D.Unit_Price,
FROM CUSTOMER C
JOIN Donut_Order I ON C.Customer_ID=I.Customer_ID
JOIN Order_LINE_ITEM ILI ON I.Donut_Order_ID = 1
JOIN DONUT D ON ILI.Donut_ID=D.Donut_ID;
我的 SQLite 技能不是很好,而且我很难理解这一点。在此先感谢您的帮助。
我认为提到的语法错误是 ,
就在 FROM
之前
and/or substr()
.
的极其奇怪的用法
您还应该修复对不存在列的引用:
ILI.Donut_Order_Number
ILI.Quantity
ILI.Donut_ID
因此我建议使用下面的代码,并不是说它完成了你最终想要做的事情,但是语法错误和其他一些明显的错误都消失了。
SELECT
strftime("%m/%d/%Y %H:%M", I.Order_Date) as "Order Date",
ILI.Donut_Order,
C.First_Name||" "||C.Last_Name AS CUSTNAME,
C.Street_Address,
C.Apartment_Number,
C.CITY,
C."STATE",
C.ZIP,
C.Home_Phone,
C.Mobile_Phone,
C.Other_Phone,
ILI.Qty,
ILI.Donut,
D.Name,
D.Description,
D.Unit_Price
FROM CUSTOMER C
JOIN Donut_Order I USING (Customer_ID)
JOIN Order_LINE_ITEM ILI ON I.Donut_Order_ID = ILI.Donut_Order
JOIN DONUT D ON ILI.Donut = D.Donut_ID;
输出(.headers on
):
Order Date|Donut_Order|CUSTNAME|Street_Address|Apartment_Number|City|State|ZIP|Home_Phone|Mobile_Phone|Other_Phone|Qty|Donut|Name|Description|Unit_Price
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|1|1|Plain|Plain Donut|1.5
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|12|2|Glazed|Glazed Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|8|3|Cinnamon|Cinnamon Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|8|4|Chocolate|Chocolate Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|5|Sprinkle|Sprinkle Donut|1.75
04/17/2017 21:02|1|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|6|Gluten-Free|Gluten-Free Donut|2.0
04/18/2017 21:02|2|Alvin Cressfol|1313 Mockingbird Lane|01|Auburn|AL|36801|3345550480|3345550480|3345555423|6|6|Gluten-Free|Gluten-Free Donut|2.0
请注意,为了使用上述代码获得良好结果,需要对样本数据进行以下两项更改。
我修复了示例数据,因为我认为 order_id 和 donut_id 被意外交换了。使用此代码:
-- fix sample input
delete from Order_Line_Item;
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(1,1,1);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(2,1,12);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(3,1,8);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(4,1,8);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(5,1,6);
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(6,1,6);
我还添加了第二个订单,以便更好地测试深度:
-- prepare the use of two orders
delete from Donut_Order;
-- use two orders, for better testing
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now')));
INSERT INTO Donut_Order (`Customer_ID`,`Order_Date`) VALUES (1,(DATETIME('now', '+1 day')));
INSERT INTO Order_Line_Item(Donut,Donut_Order,Qty) VALUES(6,2,6);
除了所有语法错误外,Order_Line_Item
和 Donut_Order
表之间没有连接。因此,您将获得所有订单行项目的组合,即使是那些与您想要的订单不匹配的项目。
联接中的 ON 子句应仅用于实际的联接条件。要进一步过滤结果,您应该改用 WHERE(这使意思更清楚,并且您会更容易注意到缺少某些连接条件):
SELECT ...
FROM Customer C
JOIN Donut_Order I USING (Customer_ID)
JOIN Order_Line_Item ILI ON I.Donut_Order_ID = ILI.Donut_Order
JOIN Donut D ON ILI.Donut = D.Donut_ID
WHERE I.Donut_Order_ID = 1;
(如果保证匹配的列同名,可以使用更简单的USING子句,你的列不一致,有的用_ID
后缀,有的不用。)