同一列上的多个 AND 条件 [Servicestack.OrmLite]
Multiple AND conditions on the same column [Servicestack.OrmLite]
我想知道是否可以使用 Servicestack.OrmLite
在同一列上设置多个 AND
条件。这是我打印出来的 SELECT
语句,但它总是 returns 0。我应该从具有 id 1016 和 17 两种规格的产品中获取产品计数。
SELECT COUNT(DISTINCT "Product"."Id")
FROM "Product"
INNER JOIN "ProductManufacturer"
ON ("Product"."Id" = "ProductManufacturer"."ProductId")
INNER JOIN "ProductSpecificationAttribute"
ON ("Product"."Id" = "ProductSpecificationAttribute"."ProductId")
WHERE ("ProductManufacturer"."ManufacturerId" = 6)
AND ("ProductSpecificationAttribute"."SpecificationAttributeOptionId" = 1016)
AND ("ProductSpecificationAttribute"."SpecificationAttributeOptionId" = 17)
一个列值不可能同时有两个值。
你想要的是:
AND
(
ProductSpecificationAttribute.SpecificationAttributeOptionId = 1016
OR
ProductSpecificationAttribute.SpecificationAttributeOptionId = 17
)
或者,更简洁:
AND
(
ProductSpecificationAttribute.SpecificationAttributeOptionId
IN (1016, 17)
)
并关闭任何强制您的工具“注入”“双”“引号”“周围”“每个”“实体”“名称”的选项,因为它会使查询文本难以管理。您还可以考虑使用别名和架构前缀,例如 INNER JOIN dbo.ProductSpecificationAttribute AS psa
...
进一步澄清后...目标是找到在不同行上同时具有这两个属性的产品,这在描述或代码 ORMLite 中并不清楚吐出来了。在这种情况下,这就是您想要的(有几种方法可以做到这一点,但是将所有内容转换为 EXISTS
还允许您从 COUNT
中删除 DISTINCT
,这永远不会免费):
SELECT COUNT(Product.Id) FROM dbo.Product AS p
WHERE EXISTS
(
SELECT 1 FROM dbo.ProductManufacturer AS pm
WHERE pm.ProductId = p.Id AND pm.ManufacturerId = 6
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId = 1016
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId = 17
);
如果 ProductSpecificationAttribute
的索引很差,这会导致两次扫描,您可以通过这样说来更改它(未经测试,但如果可以的话,我很乐意测试一下 produce a db<>fiddle :
SELECT COUNT(Product.Id) FROM dbo.Product AS p
WHERE EXISTS
(
SELECT 1 FROM dbo.ProductManufacturer AS pm
WHERE pm.ProductId = p.Id
AND pm.ManufacturerId = 6
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY psa.ProductId, psa.SpecificationAttributeOptionId
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) > 1
);
table ProductManufacturer
中有一个指向 Product
的 ProductID
列表也很奇怪——通常 Product
会有一个 ManufacturerID
指向另一个方向。
无论如何,如果 ORM 在创建基本 CRUD 之外的查询时遇到问题,您可以考虑使用 ORM 可以调用的存储过程(不幸的是,这在某种程度上是所有 ORM 的局限性 - 它们在基础知识方面非常出色,涵盖 80 % 的用例,但其他 20% 的情况很糟糕 - 不幸的是,我们大多数人很快就会需要另外 20%。
按商品分组,在HAVING
子句中设置条件,即可得到所有想要的商品id:
SELECT p.Id
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2; -- both specifications must exist
如果您想计算这些产品,您可以将上述查询用作子查询或 cte 并计算行数:
WITH cte AS (
SELECT p.Id
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2;
)
SELECT COUNT(*) FROM cte;
或者,使用 COUNT()
window 函数:
SELECT DISTINCT COUNT(*) OVER ()
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2;
我想知道是否可以使用 Servicestack.OrmLite
在同一列上设置多个 AND
条件。这是我打印出来的 SELECT
语句,但它总是 returns 0。我应该从具有 id 1016 和 17 两种规格的产品中获取产品计数。
SELECT COUNT(DISTINCT "Product"."Id")
FROM "Product"
INNER JOIN "ProductManufacturer"
ON ("Product"."Id" = "ProductManufacturer"."ProductId")
INNER JOIN "ProductSpecificationAttribute"
ON ("Product"."Id" = "ProductSpecificationAttribute"."ProductId")
WHERE ("ProductManufacturer"."ManufacturerId" = 6)
AND ("ProductSpecificationAttribute"."SpecificationAttributeOptionId" = 1016)
AND ("ProductSpecificationAttribute"."SpecificationAttributeOptionId" = 17)
一个列值不可能同时有两个值。
你想要的是:
AND
(
ProductSpecificationAttribute.SpecificationAttributeOptionId = 1016
OR
ProductSpecificationAttribute.SpecificationAttributeOptionId = 17
)
或者,更简洁:
AND
(
ProductSpecificationAttribute.SpecificationAttributeOptionId
IN (1016, 17)
)
并关闭任何强制您的工具“注入”“双”“引号”“周围”“每个”“实体”“名称”的选项,因为它会使查询文本难以管理。您还可以考虑使用别名和架构前缀,例如 INNER JOIN dbo.ProductSpecificationAttribute AS psa
...
进一步澄清后...目标是找到在不同行上同时具有这两个属性的产品,这在描述或代码 ORMLite 中并不清楚吐出来了。在这种情况下,这就是您想要的(有几种方法可以做到这一点,但是将所有内容转换为 EXISTS
还允许您从 COUNT
中删除 DISTINCT
,这永远不会免费):
SELECT COUNT(Product.Id) FROM dbo.Product AS p
WHERE EXISTS
(
SELECT 1 FROM dbo.ProductManufacturer AS pm
WHERE pm.ProductId = p.Id AND pm.ManufacturerId = 6
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId = 1016
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId = 17
);
如果 ProductSpecificationAttribute
的索引很差,这会导致两次扫描,您可以通过这样说来更改它(未经测试,但如果可以的话,我很乐意测试一下 produce a db<>fiddle :
SELECT COUNT(Product.Id) FROM dbo.Product AS p
WHERE EXISTS
(
SELECT 1 FROM dbo.ProductManufacturer AS pm
WHERE pm.ProductId = p.Id
AND pm.ManufacturerId = 6
)
AND EXISTS
(
SELECT 1 FROM dbo.ProductSpecificationAttribute AS psa
WHERE psa.ProductId = p.Id
AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY psa.ProductId, psa.SpecificationAttributeOptionId
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) > 1
);
table ProductManufacturer
中有一个指向 Product
的 ProductID
列表也很奇怪——通常 Product
会有一个 ManufacturerID
指向另一个方向。
无论如何,如果 ORM 在创建基本 CRUD 之外的查询时遇到问题,您可以考虑使用 ORM 可以调用的存储过程(不幸的是,这在某种程度上是所有 ORM 的局限性 - 它们在基础知识方面非常出色,涵盖 80 % 的用例,但其他 20% 的情况很糟糕 - 不幸的是,我们大多数人很快就会需要另外 20%。
按商品分组,在HAVING
子句中设置条件,即可得到所有想要的商品id:
SELECT p.Id
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2; -- both specifications must exist
如果您想计算这些产品,您可以将上述查询用作子查询或 cte 并计算行数:
WITH cte AS (
SELECT p.Id
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2;
)
SELECT COUNT(*) FROM cte;
或者,使用 COUNT()
window 函数:
SELECT DISTINCT COUNT(*) OVER ()
FROM Product p
INNER JOIN ProductManufacturer pm ON p.Id = pm.ProductId
INNER JOIN ProductSpecificationAttribute psa ON p.Id = psa.ProductId
WHERE pm.ManufacturerId = 6 AND psa.SpecificationAttributeOptionId IN (17, 1016)
GROUP BY p.Id
HAVING COUNT(DISTINCT psa.SpecificationAttributeOptionId) = 2;