views:

229

answers:

2

I have 3 tables:

users (id, name)

currency (id, name)

accounts (id, user_id, currency_id, amount)

And I want to read the data from accounts and present it in table-like view:

owner  currency1 currency2 currency3
1      0         0         0
2     10        20        30
3      0         5        10

Where owner is ID of accounts.owner, currency1,2,3 - (SELECT id FROM currency WHERE name = '1',etc)

I can get such result only for one specific ID:

SELECT
  SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency1') AND owner = @user) AS [currency1],
  SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency2') AND owner = @user) AS [currency2],
  SELECT amount FROM accounts WHERE currency = (SELECT id FROM currency WHERE name = 'currency2') AND owner = @user) AS [currency2]

Is it possible to get the same result for every object in users table? Without using Reporing Service, etc.

+2  A: 

Sounds like you want a Pivot table. It will be difficult to do if you have a varying number of rows in currency, but could still be done by using dynamiclly written sql.

Here's a resource from MSDN that explains how to use the pivot table: http://msdn.microsoft.com/en-us/library/ms177410.aspx

SELECT u.name, [1] AS Currency1, [2] AS Currency2, [3] AS Currency3
FROM 
(SELECT u.Name AS UserName, c.Currency_ID, a.Amount
FROM Accounts AS a WITH(NOLOCK)
JOIN Users u WITH(NOLOCK) ON a.user_id = u.user_id
) p
PIVOT
(
SUM (p.Amount)
FOR p.Currency_id IN
( [1], [2], [3] )
) AS pvt
ORDER BY pvt.UserName
Relster
Thanks for your answer! I will read more about Pivot tables. And about your example - where to have I to add 'FROM currency AS C' -- as far as I could understand it
abatishchev
+2  A: 

Use a pivot table and dynamic SQL to retrieve the columns

    DECLARE @columns VARCHAR(2000)
    SELECT @columns = STUFF(( SELECT DISTINCT TOP 100 PERCENT
    '],[' + c.name
    FROM currency AS c
    ORDER BY '],[' + c.name
    FOR XML PATH('')
    ), 1, 2, '') + ']'

    DECLARE @query NVARCHAR(4000)
    SET @query = N'SELECT UserName, ' + @columns +
    'FROM 
    (SELECT u.Name AS UserName, c.name AS CurrencyName, a.Amount
    FROM Accounts AS a WITH(NOLOCK)
    JOIN Users u WITH(NOLOCK) ON a.user_id = u.user_id
    JOIN Currency c WITH(NOLOCK) ON a.currency_id = c.currency_id
    ) p
    PIVOT
    (
    SUM (p.Amount)
    FOR p.CurrencyName IN
    ( '+ @columns +')
    ) AS pvt
    ORDER BY UserName'

EXECUTE(@query)

This was tested in SQL Server 2005

Carlos Torres
Thanks! There is no way to use only PIVOT without so complex dyn SQL?
abatishchev
If you need the columns to be dynamic (new currencies added -or deleted- or changes in a currency name) you still need dynamic SQL.
Carlos Torres