在SELECT查询中连接两个表不起作用

时间:2012-01-01 20:04:38

标签: sql sqlite count

我经营一个购物车,产品可以有其他选择。例如, product1 可以有多个选项,如:

  • 大小: S,M,L,XL

  • 颜色: 红色,蓝色,绿色

默认产品存储在customers_basket

其他所选项目存储在customers_basket_attributes

在两个表中,我插入一个名为products_unique_id的唯一键。

这是为了识别客户何时添加具有相同选项的其他产品,如果是的话 我只需要更新customers_basket表的数量字段。

如果用户插入相同的产品但具有不同的选项,products_unique_id会发生变化。

以下查询不起作用:

SELECT * FROM 
customers_basket_attributes cba, 
customers_basket cb

WHERE 

cba.products_id = cb.products_id 
AND 
cba.products_unique_id = cb.products_unique_id 
AND customers_id="1"

但是,此查询有效:

SELECT * FROM 
customers_basket cb, 
products p, 
products_description pd 
WHERE 
cb.products_id = p.products_id 
AND 
cb.products_id = pd.products_id 
AND customers_id="1"

这也有效:

SELECT * FROM 
customers_basket_attributes cba, 
products p, 
products_description pd 
WHERE 
cba.products_id = p.products_id 
AND 
cba.products_id = pd.products_id 
AND customers_id="1"

数据库结构&记录

以下是测试上述查询所需的数据库结构和记录:

DROP TABLE IF EXISTS customers_basket;
CREATE TABLE customers_basket (
  customers_basket_id INTEGER PRIMARY KEY ASC,
  customers_id int NOT NULL,
  products_id int NOT NULL,
  products_unique_id tinytext NOT NULL,  
  customers_basket_quantity int(2) NOT NULL,
  final_price decimal(15,4),
  customers_basket_date_added datetime
);

DROP TABLE IF EXISTS customers_basket_attributes;
CREATE TABLE customers_basket_attributes (
  customers_basket_attributes_id INTEGER PRIMARY KEY ASC,
  customers_id int NOT NULL,
  products_id int NOT NULL,
  products_unique_id tinytext NOT NULL,
  products_options_id int NOT NULL,
  products_options_txt varchar(64) NOT NULL default '',
  products_options_value_id int NOT NULL,
  products_options_value_txt varchar(64) NOT NULL default ''
);

此外,我已经包含了下表,即使不需要它们来测试问题查询。

DROP TABLE IF EXISTS products;
CREATE TABLE products (
  products_id int NOT NULL,
  products_quantity int(4) NOT NULL,
  products_model varchar(12),
  products_image varchar(64),
  products_price decimal(15,4) NOT NULL,
  products_date_added datetime NOT NULL,
  products_last_modified datetime,
  products_date_available datetime,
  products_weight decimal(5,2) NOT NULL,
  products_status tinyint(1) NOT NULL,
  products_tax_class_id int NOT NULL,
  manufacturers_id int NULL,
  products_ordered int NOT NULL default '0',
  PRIMARY KEY (products_id)
);

DROP TABLE IF EXISTS products_description;
CREATE TABLE products_description (
  products_id int NOT NULL,
  language_id int NOT NULL default '1',
  products_name varchar(64) NOT NULL default '',
  products_description text,
  products_url varchar(255) default NULL,
  products_viewed int(5) default '0',
  PRIMARY KEY  (products_id,language_id)
);

INSERT INTO customers_basket_attributes VALUES (1,1,1,1{4}1{3}5{5}10,4,Memory,1,4 mb);
INSERT INTO customers_basket_attributes VALUES (2,1,1,1{4}1{3}5{5}10,3,Model,5,Value);
INSERT INTO customers_basket_attributes VALUES (3,1,1,1{4}1{3}5{5}10,5,Version,10,Download: Windows - English);
INSERT INTO customers_basket_attributes VALUES (4,1,2,2{4}3{3}6,4,Memory,3,16 mb);
INSERT INTO customers_basket_attributes VALUES (5,1,2,2{4}3{3}6,3,Model,6,Premium);

INSERT INTO customers_basket VALUES(1,1,1,1{4}1{3}5{5}10,1,0,DATETIME('NOW'));
INSERT INTO customers_basket VALUES(2,1,2,2{4}3{3}6,2,0,DATETIME('NOW'));


INSERT INTO products VALUES (1,32,'MG200MMS','matrox/mg200mms.gif',299.99, DATETIME('NOW'),null,null,23.00,1,1,1,0);
INSERT INTO products VALUES (2,32,'MG400-32MB','matrox/mg400-32mb.gif',499.99, DATETIME('NOW'),null,null,23.00,1,1,1,0);
INSERT INTO `products_description` VALUES(1, 1, 'Matrox G200 MMS', '', 'www.matrox.com/mga/products/g200_mms/home.cfm', 0);
INSERT INTO `products_description` VALUES(2, 1, 'Matrox G400 32MB', '', 'www.matrox.com/mga/products/mill_g400/home.htm', 0);

更新:我刚发现它在表customers_basket_attributescustomers_basket之间失败。

productsproducts_description可以正常工作,如果与其他2个表单独检查它们。

**由于原则,我决定@Jonathan Leffler应得的赏金。不仅是因为他的答案,也是因为他努力让我理解他的答案。所以请不要试图获得这笔赏金。如果我对SO保持封锁,我希望对我的最后一次行动充满信心**

2 个答案:

答案 0 :(得分:6)

您的表格组织似乎有点奇怪,因为您通常不会期望找到包含Customers_Basket列的Customers_Basket_Attributesproducts_id。但是,从表面上看,使用现代的JOIN表示法(总是使用旧的SQL-86连接符号),你可能会追求:

SELECT cb.*, cba.*, p.*, pd.*
  FROM customers_basket            AS cb
  JOIN customers_basket_attributes AS cba ON cb.products_id = cba.products_id
  JOIN products                    AS p   ON cb.products_id = p.products_id 
  JOIN products_description        AS pd  ON cb.products_id = pd.products_id
 WHERE cb.customers_id = "1"

但是,您更有可能需要在其他(尚未识别的)列上加入Customers_Basket(CB)和Customers_Basket_Attributes(CBA),例如CBA.Basket_ID = CB.Basket_ID


架构分析

因为您没有向我们展示足够的表格模式,也没有向我们展示您尝试过或多或少的工作,所以很难为您提供更多帮助。

您现在向我们展示了表格模式,这是一个开始,但模式仍然有些神秘。特别是,您没有显示Customers_Basket(CB)和Customers_Basket_Attributes(CBA)表之间的外键关系。

你有,似乎:

CB                                         CBA
customers_basket_id (PK)                   customers_basket_attributes_id (PK)
customers_id                               customers_id
products_id                                products_id
products_unique_id                         products_unique_id
customers_basket_quantity                  products_options_id
final_price                                products_options_value_id
customers_basket_date_added                products_options_value_txt

这有点扭曲。

在我看来,对这些可能代表什么的合理解释,我希望客户(随着时间的推移)有多个篮子CB。每个篮子可能有多个项目(可能是一个,也许很多)。项目信息将在CBA表中。这将建议一个模式,如:

CREATE TABLE customers_basket
(
  customers_basket_id         INTEGER PRIMARY KEY ASC,
  customers_id                INTEGER NOT NULL REFERENCES Customers,
  customers_basket_date_added DATETIME
);

CREATE TABLE customers_basket_attributes
(
  customers_basket_attributes_id INTEGER PRIMARY KEY ASC,
  customers_basket_id            INTEGER NOT NULL REFERENCES Customers_Basket,
  products_id                    INTEGER NOT NULL REFERENCES Products,
  quantity                       INTEGER NOT NULL
);

这会将大部分产品说明留在产品说明表中。它为您提供了一个更简单的客户购物篮表 - 您可能会添加其他字段。客户篮子属性表也简单得多。

使用此结构,您可以将SQL编写为:

SELECT c.*, b.*, a.*, p.*, d.*
  FROM customers                   AS c
  JOIN customers_basket            AS b ON c.customers_id = b.customers_id
  JOIN customers_basket_attributes AS a ON b.customers_basket_id = a.customers_basket_id
  JOIN products                    AS p ON a.products_id = p.products_id 
  JOIN products_description        AS p ON p.products_id = d.products_id
 WHERE c.customers_id = "1"

我没有研究过您的产品和产品说明表,看看它们如何协同工作。

答案 1 :(得分:2)

我不是100%肯定我明白,但是这个怎么样:

SELECT * FROM 
customers_basket cb, 
products p, 
products_description pd,
customers_basket_attributes cba
WHERE 
cb.products_id = p.products_id 
AND 
cb.products_id = pd.products_id
AND
cba.products_id = cb.products_id 
AND customers_id="1"