tags:

views:

69

answers:

6

i have 3 tables see the picture

i want the sql statement which produde report like Required Report in pic.

alt text

A: 

I think the query you are looking for is...

SELECT Userid,
       UserName,
       (SELECT Dep_title
            FROM department
            WHERE USER.dep_id = department.dep_id) AS Dep_title,
       ((SELECT (SUM(amount)
             FROM Transactions
             WHERE Transactions.userid = USER.Userid AND
                   tr_type             = 'Credit') -
        (SELECT (SUM(amount)
             FROM Transactions
             WHERE Transactions.userid = USER.Userid AND
                   tr_type             = 'Debit')) AS "Balance(Debit-Credit)"
    FROM USER;

If I might be permitted a couple of observations; first, your last column title does not appear to reflect the contents of the column, and second, the haphazard capitalisation of your table and column names will lead to a great deal of trouble in the future; I recommend you use a consistent style for capitalisation and abbreviation forming.

Brian Hooper
@Brian Hooper Just for my own curiosity, is there a reason you used multiple selects instead of joins?
Shaded
I find subqueries easier to work with than joins; what you see is what you get. In this case I think it'd be preferable in any case because we want the SUMs, and there's no need to join the other table on twice to get them.If the query optimiser decides it likes a join better, it will rewrite the query anyway. But you do whatever suits; I wouldn't care to dogmatise.
Brian Hooper
Shaded - i'd imagine it's to keep the credit/debit rows seperate in the face of the aggregation
jim
@Shaded: While SQL's egregious syntax discourages the use of sub-selects, they are more logically coherent than joins, and avoid considerable head-scratching over what type of join to use and whether the join will generate more rows of output than desired. They also completely eliminate the need for the disaster that is `GROUP BY`. The relational algebra strongly favours this mode of expression via the `SUMMARIZE` operator.
Marcelo Cantos
Thanks guys, I was writing up a response with joins when this answer was posted so I was just curious if it was better or not. Now I've learned something new!
Shaded
@Marcelo Cantos; that's the Nail-Your-Colours-to-the-Mast version of what I was trying to say. I thought subqueryians were greatly outnumbered by joinists, but I know now not to lose heart!
Brian Hooper
The reason why subselects are vilified is because when correlated, they can be executed on a per row basis (read: as the number of rows increases, the performance significantly decreases). There are some tests that show that some optimizers are intelligent enough to optimize such things to being JOINs, but it's not guaranteed. Don't make assumptions - test and see.
OMG Ponies
@Brian: Actually, I'm an anti-SQL relation-model-ist :-). As @OMG rightly points out, however, it is difficult (and oft-ill-advised) to be a purist in the current milleu.
Marcelo Cantos
+1  A: 

It would be easier if amount was negative for debit transactions. Also, the balance is credit - debit, not debit - credit. In any case:

SELECT Userid, UserName, Dep_title,
       ( (SELECT COALESCE(SUM(amount), 0) FROM Transctions WHERE userid = USER.userid AND tr_type = 'Credit')
       - (SELECT COALESCE(SUM(amount), 0) FROM Transctions WHERE userid = USER.userid AND tr_type = 'Debit')
       ) AS Balance
  FROM USER
  JOIN Department USING (dep_id)
Marcelo Cantos
in this query if there is no record of debit, then the amount field is empty...
air
@air: Thanks for pointing that out. I've fixed it.
Marcelo Cantos
A: 

this should work (no need for subselects, but this isn't tested):

SELECT
  USER.Userid,
  USER.UserName,
  Department.Dep_title,
  SUM(IF(Transactions.tr_type='Credit',amount,amount*(-1))) as Balance
FROM
  USER,
  Department,
  Transactions
WHERE
  USER.Userid = Transactions.userid
AND
  USER.dep_id = Department.dep_id
GROUP BY
  USER.Userid
oezi
`IF(Transactions.tr_type='Credit',amount,amount*(-1))` should be `IF(Transactions.tr_type='Credit',amount*(-1),amount)` because "Balance(Debit-Credit)"
jigfox
+1  A: 

You could try something like this:

SELECT
  u.Userid AS Userid,
  u.UserName AS UserName,
  d.Dep_title AS Dep_title,
  SUM(IF(t.tr_type='Credit',-1*t.amount,t.amount)) AS "Balance(Debit-Credit)"
FROM USER AS u
LEFT JOIN Departement AS d USING(dep_id)
LEFT JOIN Transactions AS t ON u.Userid=t.userid
GROUP BY u.Userid
jigfox
A: 
Select U.UserId, U.Username, D.Dep_Title
    , Coalesce(Sum( Case When T.tr_type = 'Debit' Then -1 Else 1 End * T.Amount )
            ,0) As [Balance (Debit-Credit)]
From Users As U
    Join Department As D
        On D.Dep_Id = U.Dep_Id
    Left Join Transactions As T
        On T.UserId = U.UserId
Group By U.UserId, U.Username, D.Dep_Title
Thomas
why the three columns in `Group By`? Just `U.UserId` would be enough.
jigfox
@Jens F - The SQL specification requires that all columns in the Select clause that are not contained in an aggregate query must be referenced in the Group By. Thus, most DBMS enforce the same restriction. Only MySQL allows you to cheat by having fewer non-aggregate items in the Group By than the Select.
Thomas
@Thomas, thanks, I guess you're never finished learning new stuff
jigfox
A: 

I haven't tested this but you should be able to use the IF statement to work out the difference between credit and debit.

SELECT u.Userid, u.UserName, d.Dep_title, t.Balance
FROM USER As u
    LEFT JOIN Department AS d on u.dep_id = d.dep_id
    LEFT JOIN (SELECT userid, SUM(IF(tr_type = 'Debit', amount, -1*amount)) AS Balance FROM Transactions GROUP BY userid) AS t
thetaiko
Why the downvote?
thetaiko