2013-04-22 3 views
2

РЕШЕНИЕСуммируя стоимость по идентификатору, который появляется на несколько строк

Я решил ее просто, выполнив следующие действия.

SELECT table_size, sum(cost) as total_cost, sum(num_players) as num_players 
FROM 
(
    SELECT table_size, cost, sum(tp.uid) as num_players 
    FROM tournament as t 
    LEFT JOIN takes_part AS tp ON tp.tid = t.tid 
    LEFT JOIN users as u on u.uid = tp.tid 
    JOIN attributes as a on a.aid = t.attrId 
    GROUP BY t.tid 
) as res 
GROUP BY table_size 

Я не был уверен, что он будет работать, чем с другими агрегатными функциями, которые мне приходилось использовать в своей реальной SQL, но это, кажется, работает нормально. В будущем могут возникнуть проблемы, если я хочу делать другие вычисления, например, делать COUNT (DISTINCT tp.uid) во всех турнирах. Тем не менее, в этом случае это не так важно, поэтому я доволен. Спасибо за вашу помощь.

ОБНОВЛЕНИЕ !!! Вот Скрипки, который объясняет проблему: http://www.sqlfiddle.com/#!2/e03ff/7

Я хочу получить:

table_size | cost 
------------------------------- 
5   | 110 
8   | 80 

OLD POST

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

Мне нужно суммировать «затраты» на турнир в системе. По другим причинам, я должен был присоединиться с большим количеством других таблиц, делая то же стоимость появляются на несколько строк, например, так:

id | name | cost | (hidden_id) 
----------------------------- 
0 | Abc | 100 | 1 
1 | ASD | 100 | 1 
2 | Das | 100 | 1 
3 | Ads | 50 | 2 
4 | Ads | 50 | 2 
5 | Fsd | 0 | 3 
6 | Ads | 0 | 3 
7 | Dsa | 0 | 3 

Затраты в таблице выше, связаны со значением идентификатора, который не необходимо выбрать в SQL (это зависит от того, что пользователь решает во время выполнения). То, что я хочу получить, это сумма 100 + 50 + 0 = 150. Конечно, если я просто использую СУММ (стоимость), я получу другой ответ. Я пытался использовать SUM (cost)/COUNT (*) * COUNT (tourney_ids), но при определенных обстоятельствах это дает правильный результат. A (очень) простая форма запроса выглядит так:

SELECT SUM(cost) as tot_cost -- This will not work as it sums all rows where the sum appears. 
FROM t 
JOIN ta ON t.attr_id = ta.toaid 
JOIN tr ON tr.toid = t.toid -- This row will cause multiple rows with same cost 
GROUP BY *selected by user* -- This row enables the user to group by several attributes, such as weekday, hour or ids of different kinds. 

ОБНОВЛЕНИЕ. Более корректный SQL-запрос, возможно:

SELECT 
*some way to sum cost* 
FROM tournament AS t 
JOIN attribute AS ta ON t.attr_id = ta.toaid 
JOIN registration AS tr ON tr.tourneyId = t.tourneyId 
INNER JOIN pokerstuff as ga ON ta.game_attr_id = ga.gameId 
LEFT JOIN people AS p ON p.userId = tr.userId 
LEFT JOIN parttaking AS jlt ON (jlt.tourneyId = t.tourneyId AND tr.userId = jlt.userId) 
LEFT JOIN (
    SELECT t.tourneyId, 
    ta.a - (ta.b) - sum(c)*ta.cost AS cost 
    FROM tournament as t 
    JOIN attribute as ta ON (t.attr_id = ta.toaid) 
    JOIN registration tr ON (tr.tourneyId = t.tourneyId) 
    GROUP BY t.tourneyId, ta.b, ta.a 
) as o on t.tourneyId = o.tourneyId 
AND whereConditions 
GROUP BY groupBySql 

Описание таблиц

  • турнир (tourneyId, имя, attributeId)
  • атрибутов (attributeId, ..., GameID)
  • регистрация (userId, tourneyId, ...)
  • pokerstuff (gameid, ...)
  • человек (userId, ...)
  • parttaking (userId, tourneyId, ...)

Давайте предположим, что мы имеем следующее (стоимость фактически вычисляется в подзапрос, но так как он привязан к турниру, я буду рассматривать его как атрибут здесь):

турнир:

tourneyId | name   | cost 
1   | MyTournament | 50 
2   | MyTournament | 80 

и

userId | tourneyId 
1  | 1 
2  | 1 
3  | 1 
4  | 1 
1  | 2 
4  | 2 

проблема довольно проста. Мне нужно получить сумму расходов на турниры, не считая турнира более одного раза. Сумма (и все остальные агрегаты) будет динамически сгруппирована пользователем.

Большая проблема в том, что многие решения, которые я пробовал (например, SUM OVER ...), требуют, чтобы я группировал определенные атрибуты и что я не могу этого сделать. Пользовательский вопрос должен быть полностью определен групповым положением. Сумма стоимости должна суммироваться по любым атрибутам group-by, единственной проблемой является, конечно, несколько строк, в которых появляется сумма.

У кого-нибудь из вас есть какие-либо хорошие подсказки о том, что можно сделать?

+0

Какая СУБД вы используете? –

+0

Является ли стоимость на столе t - если нет, то какая таблица? Является ли hidden_id на таблице t - если нет, то какая таблица? Можете ли вы включить остальную часть существующего запроса? –

+0

Daniel - I ues PostgreSQL. – Anvariel

ответ

1

Попробуйте следующее:

select *selected by user*, sum(case rownum when 1 then a.cost end) 
from 
(
    select 
     *selected by user*, cost, 
     row_number() over (partition by t.tid) as rownum 
    FROM t 
    JOIN ta ON t.attr_id = ta.toaid 
    JOIN tr ON tr.toid = t.toid 
) a 
group by *selected by user* 

row_number используется для нумерации каждой строки с тем же турнира подряд. При суммировании затрат мы рассматриваем только те строки с rownum of 1. Все остальные строки являются дубликатами этого в отношении затрат.


С точкой зрения скрипки:

select table_size, sum(case rownum when 1 then a.cost end) 
from 
(
    SELECT 
     table_size, cost, 
     row_number() over (partition by t.tid) as rownum 
    FROM tournament as t 
    LEFT JOIN takes_part AS tp ON tp.tid = t.tid 
    LEFT JOIN users as u on u.uid = tp.tid 
    JOIN attributes as a on a.aid = t.attrId 
) a 
group by table_size 
+0

Я получаю «вызовы агрегатных функций не могут содержать вызовы функций окна». Кроме того, я знаю, что PostgreSQL не поддерживает распределенные агрегаты. Кроме того, удаление вложенного предложения я получаю «стоимость столбца» должно появляться в предложении GROUP BY или использоваться в агрегатной функции ». – Anvariel

+0

@ user2135776: Пожалуйста, ознакомьтесь с обновлением. –

+0

Это соединение с tr, которое делает вещи неправильными, поэтому нет, это тоже не сработает. Возможно, что можно сделать это с помощью двух подзапросов, но я надеялся так или иначе избежать этого. – Anvariel

0

В неоднократной стоимости такой же каждый раз, когда вы можете усреднить их по скрытому идентификатору и сделать что-то вроде этого:

WITH MrTable AS (
    SELECT DISTINCT hidden_id, AVG(cost) OVER (PARTITION BY hidden_id) AS cost 
    FROM stuff 
) 
SELECT SUM(cost) FROM MrTable; 
+0

Проблема здесь такая же, как и то, о чем я упомянул в ответе Марка Баннистера.Скрытый_id (турнирный) не может использоваться в предложении partition-by без использования в предложении group by. – Anvariel

0

(Обновлено) Учитывая, что возвращенная стоимость представляет собой общую стоимость турнира, вы можете включить дробное значение стоимости в каждую строку внутреннего выбора, чтобы общее количество всех этих значений добавлялось к тоте л стоимость (с учетом того, что значения каждого данного турнира могут появляться несколько раз), то сумма, дробная стоимости в вашем внешнем выбрать, например, так:

select table_size, sum(frac_cost) as agg_cost from 
(SELECT a.table_size , cost/count(*) over (partition by t.tid) as frac_cost 
FROM tournament as t 
LEFT JOIN takes_part AS tp ON tp.tid = t.tid 
LEFT JOIN users as u on u.uid = tp.uid 
JOIN attributes as a on a.aid = t.attrId) sq 
GROUP BY table_size 

here SQLFiddle.

+0

Я боюсь, что это не сработает, так как турнир не может использоваться в разделе «раздел by» без включения в предложение group by. Это, к сожалению, главная проблема. – Anvariel

+0

@ user2135776: Я вижу вашу точку зрения - я обновил свой ответ, чтобы разрешить это. –

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