The query I am using is below:
SELECT
b.partyID,
(select top 1 b.credit) as opening,
case when (b.total>b.credit) then b.price else '0' end as debit,
case when (b.total<b.credit) then b.price else '0' end as credit,
(select top 1 b.total) as closing
FROM tblPartyOrder b
WHERE b.date>='2014-03-06' AND b.date<='2016-03-09'
GROUP BY b.partyID, b.credit, b.total, b.price
ORDER BY b.partyID;
Result from query:
What I need:
Please help! Much obliged.
To do that, you should first create a view party_table_view to add a rownumber for each group of partyID like this :
SELECT ROW_NUMBER() OVER (PARTITION BY partyID order by partyID) as ligne, partyID , opening, debit, credit,closing
FROM dbo.party_table
second, you execute the following query :
select
a.partyID,
(select top 1 b.opening FROM party_table_view as b where a.partyID=b.partyID) as op,
SUM(a.debit),
SUM(a.credit),
(select top 1 c.closing FROM party_table_view as c
where a.partyID=c.partyID
and
(select COUNT(*) FROM party_table_view as d where c.partyID=d.partyID)
=
c.ligne
) as cl FROM party_table_view as a GROUP BY a.partyID ORDER BY a.partyID;
and here is the result as you wanted
enjoy :D !
You group by b.partyID, b.credit, b.total, b.price. This means you get one result row per b.partyID, b.credit, b.total, b.price.
Let's say these are your table's records:
partyID credit price total date 1 10 20 30 2015-10-01 1 30 20 10 2015-10-02 1 10 20 30 2015-10-03 1 30 20 50 2015-10-04 2 10 20 30 2015-10-01
then you'll get (which you could also have got with DISTINCT, as you are not using any aggregate functions):
GROUP BY clause applied:
partyID credit price total 1 10 20 30 1 30 20 10 1 30 20 50 2 10 20 30
SELECT clause applied:
partyID opening debit credit closing 1 10 20 0 30 1 30 0 20 10 1 30 20 0 50 2 10 20 0 30
In your SELECT clause you are using subqueries such as (select top 1 b.credit)
. So you are saying: "Give me one record. Of all these one records (sic) give me the top one by whatever order you like (TOP without ORDER BY). Fill this record with one value. This one value is to be b.credit
."
b.credit
is in the GROUP BY clause, so there is only one value per group. You can easily replace the whole subquery (select top 1 b.credit)
with a mere b.credit
.
Here is your query re-written:
SELECT distinct
b.partyID,
b.credit as opening,
case when b.total > b.credit then b.price else 0 end as debit,
case when b.total < b.credit then b.price else 0 end as credit,
b.total as closing
FROM tblPartyOrder b
WHERE b.date >= '2014-03-06' and b.date <= '2016-03-09'
ORDER BY b.partyID;
Now to your actual problem: You want one row per partyID
, so group by partyID
(only). You want a sum, so use the aggregate function SUM
. You want to find the first and last record per partyID, so mark them somehow. You can use the analytic function ROW_NUMBER
for this, giving these records the #1:
select
partyid,
min(case when first_is_one = 1 then credit end) as opening,
sum(case when total > credit then price else 0 end) as debit,
sum(case when total < credit then price else 0 end) as credit,
min(case when last_is_one = 1 then total end) as closing
from
(
select
po.partyid, po.credit, po.total, po.price,
row_number() over (partition by po.partyid order by po.date) as first_is_one,
row_number() over (partition by po.partyid order by po.date desc) as last_is_one
from tblpartyorder po
where po.date >= '2014-03-06' and po.date <= '2016-03-09'
) marked
group by partyid
order by partyid;
The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.