Форум: Форум PHPФорум ApacheФорум Регулярные ВыраженияФорум MySQLHTML+CSS+JavaScriptФорум FlashРазное
Новые темы: 0000000
PHP Puzzles. Авторы: Кузнецов М.В., Симдянов И.В. MySQL на примерах. Авторы: Кузнецов М.В., Симдянов И.В. PHP 5/6. В подлиннике. Авторы: Кузнецов М.В., Симдянов И.В. C++. Мастер-класс в задачах и примерах. Авторы: Кузнецов М.В., Симдянов И.В. Социальная инженерия и социальные хакеры. Авторы: Кузнецов М.В., Симдянов И.В.
ВСЕ НАШИ КНИГИ
Консультационный центр SoftTime

Форум MySQL

Выбрать другой форум

 

Здравствуйте, Посетитель!

вид форума:
Линейный форум Структурный форум

тема: Дополнительное условие к полю присоеденённому LEFT JOIN
 
 автор: Борис   (27.10.2007 в 17:06)   письмо автору
 
 

Здравствуйте!
Имеются 2 таблицы:
1) Таблица USERS
CREATE TABLE `users` (
`id` INT NOT NULL ,
`name_surname` VARCHAR( 30 ) NOT NULL
);
2) Таблица ORDERS
CREATE TABLE `orders` (
`id` INT NOT NULL ,
`user_id` INT NOT NULL ,
`order_value` INT NOT NULL ,
`value_paid` INT NOT NULL
);
order_value=СТОИМОСТЬ ЗАКАЗА
value_paid=СКОЛЬКО УЖЕ ОПЛАЧЕНО
user_id=ID пользователя совершившего заказ

Требуется одним запросом вытащить имя_фамилия, к-во оплаченных заказов, сколько ВСЕГО денег заплачено за все заказы.
Поясненние: определение того оплачен заказ или нет обязательно определяется равнеством полей orders.order_value=orders.value_paid

Не понимаю куда можно влепить это условие к order_count
По другому - вычисление order_count производить в том случае ЕСЛИ ЦЕНА ЗАКАЗА совпадает С ОПЛАЧЕННОЙ ЦЕНОЙ

select users.name_surname AS name_surname, sum(orders.value_paid) AS value_paid, count(orders.id) AS order_count FROM users LEFT JOIN orders ON orders.user_id=users.id GROUP BY users.name_surname ASC HAVING users.id=1

операторы запроса желательно не менять, дабы потом чтобы можно было производить MYSQL сортировку по всем вытащенным полям.
СПАСИБО!

   
 
 автор: EXP   (27.10.2007 в 18:20)   письмо автору
 
   для: Борис   (27.10.2007 в 17:06)
 

можно задать вопрос если можно , непойму для чего там используется HAVING users.id=1,
как я понял HAVING делает то-же что WHERE , но только после поиска в таблице и перед
выдачей результата . или я неправильно понял ?
я-бы попробовал наверное так

SELECT users.name_surname AS name_surname, SUM(orders.value_paid) AS value_paid, COUNT(orders.id) AS order_count 
    FROM users LEFT JOIN orders ON orders.user_id=users.id 
    WHERE users.id=1 AND orders.order_value=orders.value_paid
              GROUP BY users.name_surname ASC ;

и там может быть несколько одинаковых users.id ?

   
 
 автор: Борис   (27.10.2007 в 19:27)   письмо автору
 
   для: EXP   (27.10.2007 в 18:20)
 

HAVING в этом случаем заменяет WHERE - это верно. Но в данном случае нельзя использовать WHERE т.к используется оператор GROUP BY. А оператор GROUP BY в свою очередь необходим, когда происходит выборка данных единственных строк в паре с функциями которые обходят все строки таблицы после чего и делают расчёты(SUM(), COUNT()). Одинаковые USER.id могут быть лишь в таблице "заказы".

В Вашем варианте когда условие будет находить строки где совпадает id пользователя, и сумма оплаченная = сумме стоимости заказа, мне же необходимо в любом случае выбирать все строки, т.е. выводить на экран всех пользователей, и помимо этот высчитать сколько провёл полностью оплаченных заказов каждый пользователь. Чтобы позже можно было применить GROUP BY order order_coun DESC к примеру.

   
 
 автор: EXP   (27.10.2007 в 20:34)   письмо автору
 
   для: Борис   (27.10.2007 в 19:27)
 

почему-то нигде не нашёл подтверждения тому что WHERE нельзя использовать перед GROUP BY
у меня с WHERE работает что-то похожее на тысячную долю секунды быстрее чем с HAVING, если не показалось.
вам наверное придётся делать подзапрос в запросе, если COUNT и SUM считают при разных условиях. что-то похожее на это
SELECT (@id := users.id ) AS id, users.name_surname , 
    SUM(orders.value_paid) AS value_paid, 
    ( SELECT COUNT(id) FROM orders WHERE id= @id AND order_value=value_paid ) AS order_count  
    FROM users LEFT JOIN orders ON orders.user_id=users.id  
    GROUP BY users.name_surname ASC ;
только HAVING совсем убрал и добавилось id, без переменной не пробовал так делать

   
 
 автор: Борис   (27.10.2007 в 21:34)   письмо автору
 
   для: EXP   (27.10.2007 в 20:34)
 

SELECT (
@id:= users.id
) AS id, users . name_surname , sum( orders.value_paid ) AS value_paid, (

SELECT COUNT( id )
FROM orders
WHERE orders.user_id = @id
AND orders.order_value = orders.value_paid
) AS order_count

FROM users
LEFT JOIN orders ON orders.user_id = users.id
GROUP BY name_surname DESC

Все верно всё считается правильно. Но возможность отсортировать по order_count пропадает в случае GROUP BY order_count DESC

По поводу GROUP BY и HAVING
http://www.dzmrianinaski.myweb.ge/sql_groupby.asp-output=print.htm

   
 
 автор: EXP   (27.10.2007 в 22:54)   письмо автору
 
   для: Борис   (27.10.2007 в 21:34)
 

ORDER BY order_count DESC нормально сортирует вроде
а GROUP BY так и так не группирует по значениям получаемым COUNT() или sum(),
возможно недопонимаю просто чегото , но там тоже написано что просто HAVING может работать с теми значениями которые получаются только в процессе получения и поэтому с ними не может работать WHERE
мне почему-то так думается :)

   
 
 автор: Борис   (28.10.2007 в 00:29)   письмо автору
 
   для: EXP   (27.10.2007 в 22:54)
 

Мдяя=) что-то я полез не в ту степь. Правда ведь всё решается подзапросами без всякиз лефт-джойнов....В любом случае спасибо за помощь...

   
 
 автор: EXP   (28.10.2007 в 01:15)   письмо автору
 
   для: Борис   (27.10.2007 в 21:34)
 

Спасибо Вам. я тут какраз мучался мыслью какое-же ещё бывает WHERE кроме WHERE :)
насчёт LEFT JOIN даже незнаю , может и быстрее будет с ним работать , какая-то всёравно связка двух таблиц , как-бы даже GROUP BY здесь лишняя , но без неё нельзя. только опытным путём наверное выяснить можно как будет быстрее.

   
 
 автор: oradev   (28.10.2007 в 10:49)   письмо автору
 
   для: EXP   (28.10.2007 в 01:15)
 

Борис и EXP ваша задача тривиальна:

SELECT max(u.name_surname), sum(ifnull(o.value_paid, 0)), count(o.id) AS c_num
  FROM users AS u LEFT JOIN orders AS o
          ON (u.id = o.user_id AND o.value_paid = o.order_value)
 GROUP BY u.id
 ORDER BY c_num DESC;


Скажу только, что в GROUP BY никаких DESC и ASC в помине нет, данные кляузы только в ORDER BY

   
 
 автор: Борис   (28.10.2007 в 19:10)   письмо автору
 
   для: oradev   (28.10.2007 в 10:49)
 

Так в догонку, решилась проблема с ORDER BY, далее при разработке возникла новая проблема. Если подставляю условие WHERE к подзапросу выдаётся ошибка. Как задать условие where к результатам подзапроса? Спасибо!
SELECT (

@this_id := users.id
) AS this_id, users . * ,
(
SELECT SUM( value_paid )
FROM orders
WHERE id = @this_id
) AS value_paid

FROM users

WHERE value_paid >=1000
ORDER BY id DESC
LIMIT 0 , 30

   
 
 автор: oradev   (28.10.2007 в 19:31)   письмо автору
 
   для: Борис   (28.10.2007 в 19:10)
 

Борис, вы мой запрос запускали ?

   
 
 автор: Борис   (28.10.2007 в 20:46)   письмо автору
 
   для: oradev   (28.10.2007 в 19:31)
 

Да огромное спасибо, вот оно - именно то что я и искал, изящное решение в один запрос.
Но всё же интересно как решить предыдущую проблему, к чему необходимо привязать условие!?

SELECT u .name_surname , sum( ifnull( o.value_paid, 0 ) ) AS value_paid, count( o.id ) AS order_count
FROM users AS u
LEFT JOIN orders AS o ON ( u.id = o.user_id
AND o.value_paid = o.order_value )
WHERE o.value_paid >15000
GROUP BY u.id
ORDER BY order_count DESC
LIMIT 0 , 30

   
 
 автор: Борис   (28.10.2007 в 21:17)   письмо автору
 
   для: Борис   (28.10.2007 в 20:46)
 

Хммм, теперь хочу получить помимо к-ва оплаченных заказов, к-во общих заказов не зависимо от o.value_paid = o.order_value, делаю дополнительную связь в итоге получается билиберда...
SELECT u .name_surname, sum( ifnull( o.value_paid, 0 ) ) AS value_paid, count( o.id ) AS order_paid, count( o2.id ) AS order_count
FROM users AS u
LEFT JOIN orders AS o ON ( u.id = o.user_id
AND o.value_paid = o.order_value )
LEFT JOIN orders AS o2 ON ( u.id = o2.user_id )
GROUP BY u.id
ORDER BY id DESC

   
 
 автор: Борис   (28.10.2007 в 21:34)   письмо автору
 
   для: Борис   (28.10.2007 в 21:17)
 

Также, если данный запрос возвращает верные данные

SELECT u .name_surname, sum( ifnull( o.value_paid, 0 ) ) AS value_paid, count( o.id ) AS order_paid
FROM users AS u
LEFT JOIN orders AS o ON ( u.id = o.user_id
AND o.value_paid = o.order_value )
WHERE value_paid>1000
GROUP BY u.id
ORDER BY id DESC

То следующий запрос возвращает ошибку:

SELECT u .name_surname, sum( ifnull( o.value_paid, 0 ) ) AS value_paid, count( o.id ) AS order_paid
FROM users AS u
LEFT JOIN orders AS o ON ( u.id = o.user_id
AND o.value_paid = o.order_value )
WHERE order_paid>1
GROUP BY u.id
ORDER BY id DESC

#1054 - Unknown column 'order_paid' in 'where clause'

   
 
 автор: oradev   (28.10.2007 в 21:50)   письмо автору
 
   для: Борис   (28.10.2007 в 21:34)
 

Борис, все элементарно выполняется скажите условие

WHERE value_paid>1000


Что означает - где стоимость заказа конкретного! > 1000 для пользователя
или общая уже сумма заказов пользователя.
Скажите, как трактовать, я вам напишу запрос !

   
 
 автор: Борис   (28.10.2007 в 22:03)   письмо автору
 
   для: oradev   (28.10.2007 в 21:50)
 

1) WHERE value_paid>1000 где общая сумма заказов пользователя больще 1000

2) WHERE order_paid>1 где к-во оплаченных заказов больше одного

3) WHERE order_count>1 где к-во заказов больше одного(не важно оплаченных или нет)
P.S (order_count ) не знаю как вытащить к-во заказов(не важно оплаченных или нет) в связке с оплаченной суммой пользователя и к-вом оплаченных заказов

P.P.S. Оффтоп, хотелось бы узнать название толкового туториала по SQL, MYSQL где теория подверждается примерами(кроме официально мануала), рыть гугл в решении данной задачи для меня гиблое дело..=(.

   
 
 автор: Борис   (29.10.2007 в 02:21)   письмо автору
 
   для: Борис   (28.10.2007 в 22:03)
 

SELECT u .name_surname, sum( ifnull( o.value_paid, 0 ) ) AS value_paid, count( o.id ) AS order_paid
FROM users AS u
LEFT JOIN orders AS o ON ( u.id = o.user_id
AND o.value_paid = o.order_value )
GROUP BY u.id
HAVING order_paid>1
AND value_paid>1000
ORDER BY id DESC

проблема с условиями для sum, count решилась используя HAVING, осталось вытащить к-во сделанных заказов(не важно оплаченных или нет).

   
 
 автор: oradev   (29.10.2007 в 09:52)   письмо автору
 
   для: Борис   (28.10.2007 в 22:03)
 

Борис, ваш запрос:

SELECT u.name_surname,sum(o.value_paid)/count(distinct o2.id) AS sum_oplaty, count(DISTINCT o
      .id) AS cn_order_paid,count(DISTINCT o2.id)AS cn_order
  FROM    users AS u LEFT JOIN orders AS o
             ON (u.id = o.user_id AND o.value_paid = o.order_value)
       LEFT JOIN
          orders AS o2
       ON (u.id = o2.user_id)
 GROUP BY u.id,u.name_surname
 HAVING sum_oplaty > 1000 and cn_order_paid > 1 and cn_order > 1;


Что не ясно, обращайтесь поясню.

   
 
 автор: Борис   (29.10.2007 в 22:51)   письмо автору
 
   для: oradev   (29.10.2007 в 09:52)
 

Спасибо теперь всё идеально=). Вопросов нету, хотя были - но уже проштудировал материал про устранение дублирования.

   
Rambler's Top100
вверх

Rambler's Top100 Яндекс.Метрика Яндекс цитирования