【问题标题】:Query to SELECT uID if other rows of same uID have specific cell values如果相同 uID 的其他行具有特定的单元格值,则查询 SELECT uID
【发布时间】:2012-07-23 06:07:48
【问题描述】:

我正在尝试构建一个基于 PHP 的网络软件,但遇到了一个我不知道解决方案语法的问题。

基本上,我有两张桌子:

+-------------+     +---------------+
| Certs       |     | Clients       |
+-------------+     +---------------+
| userID      |     | eID           |
| prodID      |     | prods         |
| prodName    |     +---------------+
+-------------+

在这里,个人购买的每件产品都由其唯一的用户 ID 和产品的唯一产品 ID 存储。

客户就像卖家,他们自己有不同的 ID,prods 是一串以逗号分隔的产品 ID。

certs 表中的示例行如下:

userID  |  prodID  |  prodName
------------------------------
9000    |  42      |  Pen     
4234    |  54      |  Pencil
9000    |  54      |  Pencil

一个示例客户端行如下:

eID  |  prods
-------------
595  |  42,54

现在,我需要形成一个查询,返回已购买特定卖家所有产品的所有用户 ID。

例如,对于卖家 ID 595,它应该返回 9000,因为用户 ID 9000 同时购买了 42 和 54。

为方便起见,可以修改表格结构,但由于其他技术问题,我无法创建与其卖家相关的产品的标准化列表。

任何帮助将不胜感激!谢谢~

注意:另一种说法是将卖家的产品列表保存在结果类型数组中。 然后 SELECT prodID FROM certs WHERE userID = x 最后检查 prodID 的结果数组是否包含数组 prods 的所有元素。

【问题讨论】:

  • 你能解释一下你想要什么输出吗?
  • 我希望它返回购买了单个卖家所有产品的所有用户的用户ID。 IE。如果卖家 A 出售钢笔和铅笔。我想要购买钢笔和铅笔的所有用户的用户 ID。
  • 表示一个或多个产品或购买了每个产品的用户列表?
  • 是的,我想要一个购买了特定卖家所有产品的用户列表。

标签: php mysql codeigniter


【解决方案1】:

试试这个解决方案:

SELECT a.userID
FROM certs a
INNER JOIN clients b ON b.eID = 595 AND FIND_IN_SET(a.prodID, b.prods) > 0
CROSS JOIN
(
    SELECT (LENGTH(prods) - LENGTH(REPLACE(prods, ',', ''))) + 1 AS prodcnt
    FROM clients
    WHERE eID = 595
) c
GROUP BY a.userID, c.prodcnt
HAVING COUNT(1) = c.prodcnt

工作原理:

CROSS JOIN
(
    SELECT (LENGTH(prods) - LENGTH(REPLACE(prods, ',', ''))) + 1 AS prodcnt
    FROM clients
    WHERE eID = 595
) c

这样做的目的是将特定卖家拥有的 prodID 数量的计数附加到每一行。我们通过获取 CSV 列表的字符串长度并减去相同的 CSV 列表但不带逗号的长度来计算它,然后在差值上加一。示例:

字符串长度54,234,436”为10。

替换逗号:

字符串长度54234436”为8。

那么 (10-8)+1 = 3。

列表中的三个项目。


我们使用FIND_IN_SET 作为certsclients 之间的连接条件,以确定prodID 是否存在于CSV prods 列表中。

FIND_IN_SET 基本上返回 CSV 列表中特定项目的从 1 开始的索引位置。例如:

FIND_IN_SET('54', '34,76,54,128') 

将返回3,因为54 作为列表中的第三项存在。我们只需要检查它是否存在于连接条件的列表中,因此我们只需检查它是否 > 0。如果项目不在 CSV 列表中,它将返回 0。


一旦我们获得了特定客户的产品的笛卡尔连接计数和连接的表,中间结果集将如下所示:

a.userID  |  a.prodID  |  b.eID  |  b.prods  |  c.prodcnt
---------------------------------------------------------
9000      |  42        |  595    |  42,54    |  2
4234      |  54        |  595    |  42,54    |  2
9000      |  54        |  595    |  42,54    |  2

这些行中的每一行都满足连接条件。

然后我们按userID 分组以计算每个userID 的行数。由于 9000 与 c.prodcnt 中的重复值具有相同的行数,因此将返回该行。 userID 4234 被过滤掉,因为只有一行满足连接条件。

【讨论】:

  • 这很棒,但在我使用它之前,我想了解它是如何工作的。现在,我相信 SELECT (LEN...) 会为您提供该 eID 的产品数量,然后您将其与什么相提并论?因为我没有得到 INNER JOIN 的结果。 Asin,我知道您正在比较 prodID 以查看它是否存在于 prods 中,但是“clients b ON b.eID = 595 AND FIND_IN_SET(a.prodID, b.prods) > 0”的结果是什么
  • @RohanDurve-Decode141,添加了解释。也许这会让发生的事情更清楚。
  • 哥们,你不知道我有多爱你。非常感谢!
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2020-11-23
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多