Warning: file_get_contents(/data/phpspider/zhask/data//catemap/8/mysql/55.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
在MySQL实体属性值模式中选择值计数_Mysql_Sql_Count_Entity Attribute Value - Fatal编程技术网

在MySQL实体属性值模式中选择值计数

在MySQL实体属性值模式中选择值计数,mysql,sql,count,entity-attribute-value,Mysql,Sql,Count,Entity Attribute Value,我的产品有一个EAV模型,它将产品的属性存储在MySQL数据库中 我的问题是,如何有效地检索属性的特定计数(包括按所述属性过滤产品时) 我已将示例模式放在底部或sql fiddles中 更新的问题(以前的表格很乱) 我特别需要的是,当过滤这个结果集时,比如说,过滤Google具有4GB内存的产品可以得到以下结果: +--------------+-------------+-------+------------------------------------------+ | attribut

我的产品有一个EAV模型,它将产品的属性存储在MySQL数据库中

我的问题是,如何有效地检索属性的特定计数(包括按所述属性过滤产品时)

我已将示例模式放在底部或sql fiddles中

更新的问题(以前的表格很乱)

我特别需要的是,当过滤这个结果集时,比如说,过滤Google具有4GB内存的产品可以得到以下结果:

+--------------+-------------+-------+------------------------------------------+
| attributeId  |    value    | count |                                                                                                 |
+--------------+-------------+-------+------------------------------------------+
| 1            | Google      |     3 | Google with 4GB RAM                                                                             |
| 1            | Apple       |     2 | Apple with 4GB RAM (for active filters, show all options that match only the other filters)     |
| 1            | Microsoft   |     1 | Microsoft with 4GB RAM (for active filters, show all options that match only the other filters) |
| 1            | Sony        |     1 | Sony with 4GB RAM (for active filters, show all options that match only the other filters)      |
| 2            | Phone       |     1 | 1 Phone with 4GB RAM (matching both active filters)                                             |
| 3            | 4GB         |     3 | Even though it's an active filter, all Google products have 4GB RAM                             |
| 4            | Mali 200    |     1 |                                                                                                 |
| 4            | GMA 650     |     1 |                                                                                                 |
| 5            | Black       |     2 |                                                                                                 |
| 5            | Gray        |     1 |                                                                                                 |
| availability | unavailable |     3 |                                                                                                 |
| price        | > 250       |     2 |                                                                                                 |
| price        | 0-50        |     1 |                                                                                                 |
+--------------+-------------+-------+------------------------------------------+
总之,如果该属性是按筛选的,则需要显示该属性的所有值以及与所有其他(N-1)过滤器匹配的计数

如果未按筛选,则需要显示与所有N个筛选器匹配的计数

另外,产品表中还有两个需要处理的特殊属性(可用性和价格)。目前正在为这些人建立一个联盟

例如:

Attributes: A, B, C, D ,E, F
Filters: A, C, D
Result:
A (Active Filter) - Values with counts that match filters C, D
B - Values with counts that match filters A, C, D
C (Active Filter) - Values with counts that match filters A, D
D (Active Filter) - Values with counts that match filters C, D
E - Values with counts that match filters A, C, D
F - Values with counts that match filters A, C, D
我当前使用的查询是:

更新 稍微改变了以前的查询,现在它给出了正确的结果,但是它仍然非常慢,我不确定我是否想用它投入生产

(
    SELECT 
        'availability' AS attributeId, 
        availability as value,
      count(1) as 'count'
   FROM (
        SELECT p.id, p.availability FROM Products p
        JOIN ProductAttributes pa ON
            pa.productId = p.id
        WHERE
            (pa.attributeId = 1 AND pa.value = 'A1-Value A')
        GROUP BY p.id, p.availability
        HAVING (
            COUNT(*) = 1
        )
    ) AS pf
    GROUP BY availability
)
UNION
(
    SELECT 
        'price' AS attributeId, 
        case 
        when (price) between 0 and 50 then '0-50'
        when (price) between 50 and 100 then '51-100'
        when (price) between 100 and 150 then '101-150'
        when (price) between 150 and 200 then '151-200'
        when (price) between 200 and 250 then '201-250'
      ELSE '> 250'
      end as value,
      count(1) as 'count'
   FROM (
        SELECT p.id, p.price FROM Products p
        JOIN ProductAttributes pa ON
            pa.productId = p.id
        WHERE
            (pa.attributeId = 1 AND pa.value = 'A1-Value A')
        GROUP BY p.id, p.price
        HAVING (
            COUNT(*) = 1
        )
    ) AS pf
    GROUP BY value
)   
UNION
(
    SELECT 
        pfa.attributeId, pfa.value, COUNT(*)
    FROM (
            SELECT p.id FROM Products p
            JOIN ProductAttributes pa ON
                pa.productId = p.id
            GROUP BY p.id
        ) AS pf
         JOIN ProductAttributes pfa ON
            pfa.productId = pf.id
         WHERE (
            NOT (pfa.attributeId = 1 AND pfa.value = 'A1-Value A')
         )
    GROUP BY pfa.attributeId, pfa.value
)
UNION
(
    SELECT 
        pfa.attributeId, pfa.value, COUNT(*)
    FROM (
            SELECT p.id FROM Products p
            JOIN ProductAttributes pa ON
                pa.productId = p.id
            WHERE
                (pa.attributeId = 1 AND pa.value = 'A1-Value A')
            GROUP BY p.id
            HAVING (
                COUNT(*) = 1
            )
        ) AS pf
         JOIN ProductAttributes pfa ON
            pfa.productId = pf.id
         WHERE
         (
            (pfa.attributeId = 1 AND pfa.value = 'A1-Value A')
         )

    GROUP BY pfa.attributeId, pfa.value
)

然而,它并没有完全返回正确的结果,而且它有点笨重,我希望有人知道如何正确地执行此操作

非常感谢

示例模式

CREATE TABLE `Products` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `categoryId` INT(11) NULL DEFAULT NULL,
    `name` VARCHAR(255) NOT NULL,
    `availability` VARCHAR(255) NOT NULL,
    `price` FLOAT NOT NULL,
    `discount` FLOAT NULL DEFAULT NULL,
    `active` INT(11) NOT NULL,
    PRIMARY KEY (`id`),
    INDEX `price` (`price`),
    INDEX `categoryId` (`categoryId`),
    INDEX `discount` (`discount`),
    FULLTEXT INDEX `name` (`name`)
);

INSERT INTO `Products` (`id`, `categoryId`, `name`, `availability`, `price`, `discount`, `active`)
VALUES ('1', '1', 'Stadia', 'unavailable', '50', '4.06', true),
('2', '1', 'Pixel 3', 'available', '500', '4.06', true),
('3', '1', 'Chromebook', 'unavailable', '300', '4.06', true),
('4', '1', 'Mac Pro', 'unavailable', '1200', '4.06', true),
('5', '1', 'iPhone', 'unavailable', '1000', '4.06', true),
('6', '1', 'iPad', 'available', '400', '4.06', true),
('7', '1', 'Playstation 4', 'unavailable', '400', '4.06', true),
('8', '1', 'Xperia Phone', 'unavailable', '300', '4.06', true),
('9', '1', 'Surface Pro', 'available', '800', '4.06', true),
('10', '1', 'Windows Phone 7 Phone', 'unavailable', '300', '4.06', true),
('11', '1', 'Windows 10 PC', 'unavailable', '2000', '4.06', true),
('12', '1', 'XBOX', 'available', '500', '4.06', true);



CREATE TABLE `Attributes` (
    `id` INT(11) NOT NULL AUTO_INCREMENT,
    `textId` VARCHAR(255) NOT NULL,
    `name` VARCHAR(255) NOT NULL,
    PRIMARY KEY (`id`)
);

INSERT INTO `Attributes` (`id`, `textId`, `name`)
VALUES ('1', 'Brand', 'brand'),
('2', 'Type','type'),
('3', 'RAM', 'ram'),
('4', 'GPU', 'gpu'),
('5', 'Color', 'color');

CREATE TABLE `ProductAttributes` (
    `attributeId` INT(11) NOT NULL,
    `productId` INT(11) NOT NULL,
    `value` VARCHAR(255) NULL DEFAULT NULL,
    PRIMARY KEY (`attributeId`, `productId`),
    INDEX `ValueIndex` (`value`),
    INDEX `AttrIndex` (`attributeId`)
);

INSERT INTO `ProductAttributes` (`attributeId`, `productId`, `value`)
VALUES 
('1', '1','Google'),
('1', '2', 'Google'),
('1', '3', 'Google'),
('1', '4', 'Apple'),
('1', '5', 'Apple'),
('1', '6', 'Apple'),
('1', '7', 'Sony'),
('1', '8', 'Sony'),
('1', '9', 'Microsoft'),
('1', '10', 'Microsoft'),
('1', '11', 'Microsoft'),
('1', '12', 'Microsoft'),
('2', '1','Game Console'),
('2', '2', 'Phone'),
('2', '3', 'Computer'),
('2', '4', 'Computer'),
('2', '5', 'Phone'),
('2', '6', 'Tablet'),
('2', '7', 'Game Console'),
('2', '8', 'Phone'),
('2', '9', 'Tablet'),
('2', '10', 'Phone'),
('2', '11', 'Computer'),
('2', '12', 'Game Console'),
('3', '1', '4GB'),
('3', '2', '4GB'),
('3', '3', '4GB'),
('3', '4', '6GB'),
('3', '5', '4GB'),
('3', '6', '4GB'),
('3', '7', '8GB'),
('3', '8', '4GB'),
('3', '9', '6GB'),
('3', '10', '4GB'),
('3', '11', '8GB'),
('3', '12', '8GB'),
('4', '2', 'Mali 200'),
('4', '3', 'GMA 650'),
('4', '4', 'GMA 650'),
('4', '5', 'Mali 400'),
('4', '6', 'Mali 200'),
('4', '7', 'Radeon'),
('4', '8', 'Mali 400'),
('4', '9', 'GMA 650'),
('4', '10', 'Mali 400'),
('4', '11', 'Nvidia'),
('4', '12', 'Radeon'),
('5', '1','Black'),
('5', '2', 'Black'),
('5', '3', 'Gray'),
('5', '4', 'Gray'),
('5', '5', 'Black'),
('5', '6', 'Black'),
('5', '7', 'Black'),
('5', '8', 'Blue'),
('5', '9', 'Gray'),
('5', '10', 'Blue'),
('5', '11', 'Black'),
('5', '12', 'Green');

如果我理解正确,您希望产品的所有属性值对都满足具有两个指定属性的条件

如果是这样,我将使用
exists
来识别产品,然后仅聚合:

select pa.attributeId, pa.value, count(*)
from ProductAttributes pa
where exists (select 1
              from ProductAttributes pa2
              where pa2.productId = pa.productId and
                    pa2.attributeId = 1 and
                    pa2.value = 'A1-Value A'
             ) and
      exists (select 1
              from ProductAttributes pa2
              where pa2.productId = pa.productId and
                    pa2.attributeId = 3 and
                    pa2.value = 'A3-Value A'
             ) 
group by pa.attributeId, pa.value;

是一个dbfiddle。

如果我理解正确,您希望产品的所有属性值对都满足具有两个指定属性的条件

如果是这样,我将使用
exists
来识别产品,然后仅聚合:

select pa.attributeId, pa.value, count(*)
from ProductAttributes pa
where exists (select 1
              from ProductAttributes pa2
              where pa2.productId = pa.productId and
                    pa2.attributeId = 1 and
                    pa2.value = 'A1-Value A'
             ) and
      exists (select 1
              from ProductAttributes pa2
              where pa2.productId = pa.productId and
                    pa2.attributeId = 3 and
                    pa2.value = 'A3-Value A'
             ) 
group by pa.attributeId, pa.value;

是一个很难回答的问题。

这是一个很长的问题,我仍然不明白这意味着什么:“但我还需要提取属性计数以显示在筛选栏上。”样本数据和期望的结果将非常有用。尝试将其清除一点,希望它更有意义。此外,fiddles中还有一些示例数据,我希望得到的结果是“巨型联合查询”返回的结果,但我希望以更高效的方式得到这些数据。这是一个很长的问题,我仍然不明白这意味着什么:“但我还需要提取属性计数以显示在筛选栏上。”样本数据和期望的结果真的会有帮助。尝试清理一下,希望它更有意义。此外,fiddles中还有一些示例数据,我希望得到的结果是“巨型联合查询”返回的结果,但我希望以更高效的方式获得这些数据,但这并不是我想要的结果。我更新了这个问题(希望)让它更清楚。基本上,我需要的是获得只匹配一个活动过滤器的值,以及匹配所有其他过滤器的值。这个只做后面的部分。这有意义吗?@overburn。如果您只需要一个过滤器,请使用
而不是
。True,但这只会给出属性1的特定值的计数,而我需要获取属性1的所有计数,这些计数也与属性3相匹配,反之亦然。此外,如果我在混合中添加第三个条件,属性1必须按2和3、2按1和3、3按1和2进行过滤;不幸的是,我不知道该如何处理这个问题。谢谢,但不完全是我想要的。我更新了这个问题(希望)让它更清楚。基本上,我需要的是获得只匹配一个活动过滤器的值,以及匹配所有其他过滤器的值。这个只做后面的部分。这有意义吗?@overburn。如果您只需要一个过滤器,请使用
而不是
。True,但这只会给出属性1的特定值的计数,而我需要获取属性1的所有计数,这些计数也与属性3相匹配,反之亦然。此外,如果我在混合中添加第三个条件,属性1必须按2和3、2按1和3、3按1和2进行过滤;不幸的是,不确定如何在该查询中处理此问题。