2016-02-05 4 views
1

У меня есть следующая схема:Как подсчитать количество записей по подстроки в одном из полей

CREATE TABLE foo(
    company_name TEXT, 
    product_name TEXT 
); 

INSERT INTO foo VALUES("first_company|Live", "some_product"); 
INSERT INTO foo VALUES("first_company|Demo", "some_product"); 
INSERT INTO foo VALUES("second_company|Live", "another_product"); 
INSERT INTO foo VALUES("third_company|Demo", "another_product"); 

Мне нужно подсчитать количество проданных товаров, на реальных и демо-серверов, поэтому я попытался следующий запрос для подсчета живых серверов на первый:

SELECT product_name, COUNT(SUBSTRING_INDEX(company_name, '|', 1) LIKE '%Live%') AS count 
FROM `foo` GROUP BY product_name ORDER BY count DESC; 

Но это дает мне следующий результат:

product_name count 
some_product 2 
another_product 2 

Я ожидал увидеть подсчет == 1 для обоих продуктов, потому что каждый из них был установлен только на одном реальном сервере.

Что я делаю неправильно? Как добиться такого поведения?

+1

Что вы делаете неправильно? Хранение Live/Demo в том же столбце, что и название компании, является плохой идеей. – jarlh

ответ

4

Измените свой запрос немного. Избавиться от группы и подсчета, и вы увидите, что происходит:

SELECT product_name, SUBSTRING_INDEX(company_name, '|', 1) like '%Live%' AS count 
FROM `foo` ORDER BY count DESC; 

возвращается

another_product 0 
some_product 0 
some_product 0 
another_product 0 

Посмотрите на то, почему это:

SELECT product_name, SUBSTRING_INDEX(company_name, '|', 1) AS count 
FROM `foo` ORDER BY count DESC; 


another_product third_company 
another_product second_company 
some_product first_company 
some_product first_company 

Попробуйте вместо этого:

SELECT product_name, company_name like '%Live%' AS count 
FROM `foo` ORDER BY count DESC; 

Которые возвраты:

some_product 1 
another_product 1 
another_product 0 
some_product 0 

Так что вы на самом деле хотите запустить это:

SELECT product_name, count(company_name like '%Live%')>0 AS count 
FROM `foo` 
group by product_name 
ORDER BY count DESC; 

Который возвращает то, что вы хотите.

Ваша проблема заключалась в том, что вы делали чек, но затем подсчитывали ВСЕ результаты, а не только, где были сопоставлены критерии.

Действительно лучший способ сделать это, и которые сделали бы операцию подсчета функции более ясно, как это:

SELECT product_name, COUNT(*) AS count 
FROM `foo` 
where company_name LIKE '%Live%' 
GROUP BY product_name ORDER BY count DESC; 

Так COUNT (*) выбирает, сколько записей есть вы группировку по название продукта, поэтому вы получите одну строку для каждого имени продукта, а количество подсчитывает, сколько записей есть с этим именем продукта.

Фильтр WHERE означает, что вы получаете только записи, в которых имя_компании, например, «% Live%» (это то, что ваш вопрос ищет).

Итак, count (*) покажет, сколько записей есть для каждого product_name, удовлетворяющего этому критерию.

Скажите, что вам нужен счет каждого продукта для живых и демонстрационных рядов. Я добавил несколько строк в таблицу, чтобы продемонстрировать это.foo теперь выглядит следующим образом:

third_company | Демо another_product first_company | Живая some_product first_company | Демо some_product second_company | Живите another_product fourth_company | Демо another_product fourth_company | Демо a_third_product

так, если у вас есть столбец ваш запрос

company_name like '%Live%' 

оно вернет 0, если это не так, как Live, 1 если есть. Теперь, группировка по названию продукта, что вы хотите, чтобы SUM этого столбца, так что вы получите количество строк, где это верно:

SELECT 
    product_name, 
    sum(company_name like '%Live%') AS count_live, 
    sum(company_name like '%Demo%') AS count_demo 
FROM `foo` group by product_name 
; 

который возвращает:

another_product 1 2 
some_product 1 1 
a_third_product 0 1 

Кажется, вы хотели сумму всех вдоль!

+0

Я только заметил, что я пытался найти слово 'Live' в части ** перед ** символом трубы ('|'), а не после него – FrozenHeart

+1

Вам все равно нужно настроить то, что вы используете COUNT(). –

+0

Я до сих пор не понимаю, как работает «COUNT», затем – FrozenHeart

1

Не храните две части информации в одном и том же поле! В противном случае вы столкнетесь с удобочитаемостью, усложнением запросов и проблемами производительности быстрее, чем вы можете сказать «узкое место».

Вы можете разделить эти из довольно легко, что-то вроде:

CREATE TABLE foo(
    company_name TEXT, 
    product_name TEXT, 
    status TINYINT(1) NOT NULL, 
); 

INSERT INTO foo VALUES("first_company", "some_product", 1); 
INSERT INTO foo VALUES("first_company", "some_product", 0); 
INSERT INTO foo VALUES("second_company", "another_product", 1); 
INSERT INTO foo VALUES("third_company", "another_product", 0); 

Затем запросы становятся проще:

SELECT product_name, SUM(status) AS live_count 
    FROM `foo` 
GROUP BY product_name 
ORDER BY live_count DESC; 

Вы должны, вероятно, будет хранить ваши компании и продукты в различных таблицах также и ссылки это по id .. но это совершенно новый чайник веселья.

+0

Эта таблица уже существует. Я не знаю, почему автор решил сохранить эту информацию в том же поле – FrozenHeart

+0

@FrozenHeart. Мой совет: Если вы можете, измените структуру. Если вы не можете, обратитесь к автору или тому, кто может и изменит структуру! Если вам нужно «жить» или «демонтировать» на имя, вы можете сделать это на прикладном уровне :) – Arth

Смежные вопросы