SQLite复杂加入查询四个表

时间:2017-04-16 19:17:56

标签: sqlite join multiple-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技能并不是很好,而且我很难搞清楚这一点。提前感谢您的帮助。

2 个答案:

答案 0 :(得分:2)

我认为上面提到的语法错误是,之前的FROM 和/或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);

答案 1 :(得分:0)

除了所有语法错误外,Order_Line_ItemDonut_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后缀,有些则不使用。)