2015-04-28 99 views
3

我有一個多對多的關係,我想選擇特定字段的總和以及所有必要的數據。我只是通過代碼來解釋我的情況。SQL查詢:如何添加「sum」以及相應的數據

首先,這裏有相關的表結構:

CREATE TABLE `products` (
    `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    `name` text, 
    `description` text, 
    `price` float, 
    `picture` varchar(255) 
); 

CREATE TABLE `orders_products` ( 
     `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
     `quantity` integer, 
     `status` boolean, 
     `product_id` integer, 
     `order_id` integer, 
     FOREIGN KEY(`product_id`) REFERENCES "products" ("id"), 
     FOREIGN KEY(`order_id`) REFERENCES "orders" ("id") 
    ); 

CREATE TABLE `orders` (
    `id` integer NOT NULL PRIMARY KEY AUTOINCREMENT, 
    `created_at` datetime, 
    `updated_at` datetime, 
    `user_id` integer, 
    FOREIGN KEY(`user_id`) REFERENCES "users" ("id") 
); 

基本上我現在已經做了,是這樣的:

select 
"products".name, 
"products".price, 
"orders_products"."order_id", 
"orders_products"."product_id" 
from "products" 
inner join "orders_products" on "orders_products"."product_id" = "products"."id" 
where "orders_products"."order_id" in (1, 2) 

這將產生以下結果:

name   price order_id product_id 
"coca cola"  "2.35"  "1"  "1" 
"snickers"  "1.25"  "1"  "2" 
"snickers"  "1.25"  "2"  "2" 
"popcorn"  "1.19"  "2"  "3" 

但是,如果我想「總結」價格,並根據order_id訂購:

select 
sum ("products".price) as _sum, 
"products".name, 
"products".price, 
"orders_products"."order_id", 
"orders_products"."product_id" 
from "products" 
inner join "orders_products" on "orders_products"."product_id" = "products"."id" 
where "orders_products"."order_id" in (1, 2) 
group by "orders_products"."order_id" 

我得到以下結果:

_sum name  price order_id product_id 
"3.6" "snickers" "1.25"  "1"  "2" 
"2.44" "popcorn" "1.19"  "2"  "3" 

什麼其實我喜歡:

name   price order_id product_id _sum 
"coca cola"  "2.35"  "1"  "1"   "3.6" 
"snickers"  "1.25"  "1"  "2"   "3.6" 
"snickers"  "1.25"  "2"  "2"   "2.44" 
"popcorn"  "1.19"  "2"  "3"   "2.44" 

這甚至可能嗎?

回答

3

你可以做的是投影sums每個order id作爲派生表,然後再加入你的原始查詢回派生表,這將讓你展現sum爲每個順序列:

select 
    p.name, 
    p.price, 
    op.order_id, 
    op.product_id, 
    Totals.theSum 
from products p 
    inner join orders_products op on op.product_id = p.id 
    inner join 
    (select sum(p.price) as theSum, 
    op.order_id 
    from products p 
    inner join orders_products op on op.product_id = p.id 
    where op.order_id in (1, 2) 
    group by op.order_id) AS Totals 
on Totals.order_id = op.order_id; 

過濾已在內部派生表上完成,因此不需要重複。

SqlFiddle here

+0

謝謝你在原崗位的變化,現在它完美的作品! – uglycode

+0

實際上,我已經改變了一些SQL,可以在這裏看到:https://gist.github.com/javascrewpt/4564a6cf359c847131a5,基本上我已經把'where op.order_id in(1,2)'從「內連接」的「選擇」中刪除。這是否會改變一切? – uglycode

+1

它不會改變結果(因爲是內連接),但它可能會影響性能 - 如果您查看[two Fiddles](http://sqlfiddle.com/)的兩個執行計劃(鏈接在底部) #!5/fe392/1)你會注意到不同的執行計劃),儘管說實話,我們需要更多的數據。確保你索引外鍵(我已經這樣做了)。如果性能真的下降,請考慮在派生表「總計」和外部查詢中應用過濾器。 – StuartLC