I have two tables
tblA(sn, ID int pk, name varchar(50), amountA decimal(18,2))
and
tblB(ID int fk, amountB decimal(18,2))
here: tblA occures only once and tblB may occure multiple time
I need the query to display data like:
sn ID name AmountA amountB Balance
1 1001 abc 5000.00 5000.00
2 1002 xyz 10000.00
1002 4000.00 6000.00 (AmountA-AmountB)
3 1003 pqr 15000.00
1003 4000.00
1003 3000.00
1003 2000.00 6000.00 (AmountA-sum(AmountB))
Please ask if any confusion
I tried using lag and lead function but I couldnot get the desire result, Please help.
Since you are using SQL Server 2012, you can use a partition with an aggregate function (SUM):
SELECT t.sn,
t.ID,
t.name,
t.credits AS AmountA,
t.debits AS amountB,
SUM(t.credits - t.debits) OVER (PARTITION BY t.ID ORDER BY t.debits, t.credits) AS Balance
FROM
(
SELECT sn,
ID,
name,
AmountA AS credits,
0 AS debits
FROM tblA
UNION ALL
SELECT 0 AS sn,
ID,
NULL AS name,
0 AS credits,
amountB AS debits
FROM tblB
) t
ORDER BY t.ID,
t.debits,
t.credits
Explanation:
Since the records in tables A and B each represent a single transaction (i.e. a credit or debit), using a UNION query to bring both sets of data into a single table works well here. After this, I compute a rolling sum using the difference between credit and debit, for each record, for each ID partition group. The ordering is chosen such that credits appear at the top of each partition while debits appear on the bottom.
Related
I have two tables joined like this:
SELECT count(DISTINCT T1.ContractNumber) AS nr_of_contracts,
count(T3.DateofInstallmentPayment) AS nr_of_paid_installents,
count(T3.DateofDueInstallment) AS nr_of_installments,
sum(T1.DisbursementAmount) AS disbursed_amount
FROM q.T1
LEFT JOIN q.T3
ON T1.ContractNumber=T3.ContractNumber
WHERE DateOfDisbursement BETWEEN '2019-12-01' AND '2019-12-31'
AND T3.DateofDueInstallment < GETDATE()
where T1 table contains data about clients (per contract number) and T3 about their payment schedules (per every instalment).
What I want is to have paid off amount (disbursement amount) of contracts from table T1 (aggregated by contract number) and not by every instalment. When I tried to select just sum(T1.Disbursement amount) then I receive sum but for all instalment which is incorrect.
T1:
Contract Number
DisbursementDate
Disbursement Amount
1
2019-12-01
1000
2
2019-12-01
2000
3
2019-12-01
3000
T3:
Contract Number
DateofDueInstallment
DateofInstallmentPayment
1
2020-01-01
2020-01-01
1
2020-02-01
2020-02-06
1
2020-03-01
2020-04-01
What I get after joining two tables for Contract Number = 1 is sum(DisbursementAmount) = 3000.
Contract Number
sum(DisbursementAmount)
1
3000
What I want after joining two tables for Contract Number = 1 is sum(DisbursementAmount) = 1000.
Contract Number
sum(DisbursementAmount)
1
1000
Something like this,not tested - a subquery with a different aggregation column
SELECT T1.product, T1.NrOfInstallment, count(DISTINCT T1.ContractNumber),
SELECT paid_amound FROM(SELECT ContractNumber, sum(tt.DisbursementAmount + (tt.ContractNumber*0.01))
- sum(tt.ContractNumber*0.01) as paid_amount
FROM abc.T1 as tt WHERE tt.ContractNumber = T1.ContractNumber GROUP BY ContractNumber) AS t)
FROM abc.T1
LEFT JOIN bde.T3
ON T1.ContractNumber=T3.ContractNumber
GROUP BY T1.product, T1.NrOfInstallment
I am newly in sql, and I am confusing with these two query in sql server with inner join or another cartesian products.
Query 1:
SELECT TOP 3
A.STUDENT_ID,
A.STUDENT_NAME,
DOB,
CGPA,
B.STUDENT_ID
FROM
STUDENT A
INNER JOIN
STUDENT_INFO B ON A.STUDENT_NAME = B.STUDENT_NAME
ORDER BY
B.STUDENT_ID ASC
Query 2:
SELECT
A.STUDENT_ID,
A.STUDENT_NAME,
DOB,
CGPA,
C.STUDENT_ID
FROM
STUDENT A
INNER JOIN
(SELECT TOP 3 *
FROM STUDENT_INFO
ORDER BY STUDENT_ID) C ON A.STUDENT_NAME = C.STUDENT_NAME
Below are the outputs (notice the student_id):
Query 1 output:
STUDENT_ID STUDENT_NAME DOB CGPA STUDENT_ID
------------------------------------------------------------------------
4 Laura 1981-12-22 00:00:00.000 3.00 400
10 Elis 1990-10-28 00:00:00.000 3.00 400
9 Wise 1987-11-11 00:00:00.000 3.00 499
Query 2 Output
STUDENT_ID STUDENT_NAME DOB CGPA STUDENT_ID
------------------------------------------------------------------------
4 Laura 1981-12-22 00:00:00.000 3.00 400
9 Wise 1987-11-11 00:00:00.000 3.00 499
10 Elis 1990-10-28 00:00:00.000 3.00 400
My question is, both join queries are the same meaning (for my understanding), but the output is a difference (query 1 are wrong and query 2 are correct which order by student_id in ascending order), so what's the difference between query 1 and query 2? Which query should we use for more accurate output?
Thank you.
The first query orders the final result set by the STUDENT_ID, so the records are in the order you expect.
The second query orders the sub-query being joined by STUDENT_ID (effectively restricting the records being joined from that table to the first 3 records, as ordered by ID), but that ordering has no effect on the subsequent JOIN. You haven't specified any ordering on the final result set, so the DB will just give you the records in whatever order it fetched them.
They do not mean the same. In your query 2, the ORDER BY STUDENT_ID is only effective for the TOP 3 of your subquery C. In a subquery, in general ORDER BY is not accepted to use because the optimiser will not preserve ORDER BY on later join.
This is not a silly behaviour of optimisers but they have no way to preserve the ORDER BY. Imagine if you also turn STUDENT A into (select top 3 * from STUDENT order by STUDENT_ID desc) A, then should it sort it ascending or descending for you?
I have tbl_Orders:
OrderNumber ProductCode Qty OrderDate SentDate
---------------------------------------------------------------
1000 A 100 2018-03-01 00:30:51 2018-03-02
1000 A 150 2018-03-12 04:31:54 2018-03-13
1000 B 150 2018-03-11 03:34:51 2018-03-14
1001 C 200 2018-03-01 00:30:51 2018-04-02
1002 D 200 2018-03-01 00:30:51 2018-04-15
I want to write a query to get result like:
OrderNumber Qty MAXOrderDate MAXSentDate
------------------------------------------------
1000 400 2018-03-12 04:31:54 2018-03-14
1001 200 2018-03-01 00:30:51 2018-04-02
1002 200 2018-03-01 00:30:51 2018-04-15
From my newbie perspective it looks like I need 'group by OrderNumber'. But I am not sure what else. And the second problematic thing is "MAXOrderDate" or "MAXSentDate". I also don't know how to select max value from Date.
I really appreciate any help.
Simple,
It should be - As long as you are aggregating data you need not group by that column (eg.. min, max, avg etc.,.. so your original idea of groupby ordernumber should be sufficient)
Try the sql
select
tbl_Orders.ordernumber as OrderNumber
, sum(tbl_Orders.qty) as qty
,max(tbl_Orders.orderdate) as orderdate
,max(tbl_Orders.sentdate) as sentdate
from tbl_Orders
group by
tbl_Orders.ordernumber
You have to sum Qty, max on MAXOrderDate and max on MAXSentDate and then group by OrderNumber, like:
SELECT OrderNumber, sum(Qty) As Qty, max(MAXOrderDate) As OrderDate, max(MAXSentDate) AS SentDate
FROM tbl_Orders (NOLOCK)
GROUP BY OrderNumber
I would use NOLOCK to avoid other queries to be blocked in hight performance environments. Be aware that NOLOCK could bring in the result records that are in transactions that are not yet commited.
I wrote a query to combine records in multiple tables. Tables named by Purchase Order, Purchase Order Item
[ Note: The column names are not original names, it just for a model data]
In purchase order table have the order details like this,
id date vendorid totalitems totalqty grossamnt netamnt taxamt
----------------------------------------------------------------------------
1 03/10/17 00001 2 6 12000 13000 1000
Purchase Order Item table have the order details like this,
poid id productcode qty rate tax(%) taxamnt total
--------------------------------------------------------
1 1 12001 3 6000 2.5 500 6500
2 1 12000 3 6000 2.5 500 6500
My Query is,
select po.POID,po.SupplierId,po.TotalItems from
PurchaseOrder po, PurchaseOrderItem poi where po.POID=poi.POID group by
po.POID, po.SupplierId,po.TotalItems
Query returns,
id vendorid totalitems
--------------------------
1 00001 2
1 00001 2
Expected Output is,
id vendorid totalitems
------------------------
1 00001 2
You are using an outdated join method, have a read here:
ANSI vs. non-ANSI SQL JOIN syntax
You are also joining to another table, but never use it:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po, PurchaseOrderItem poi
where po.POID=poi.POID
group by po.POID, po.SupplierId,po.TotalItems
Can just be:
select po.POID,po.SupplierId,po.TotalItems
from PurchaseOrder po
group by po.POID, po.SupplierId,po.TotalItem
OR
select DISTINCT
po.POID,
po.SupplierId,
po.TotalItems
from PurchaseOrder po
I have the following table (sql server) and i'm looking for a query to select the last two rows with all fields:
order by created_at
group by / distinct type_id
id type_id some_value created_at
1 B mk2 2016-10-01 00:00:00.000
2 A mbs 2016-10-01 10:02:39.077
3 B sa 2016-10-02 10:03:08.123
4 A xc 2016-10-02 10:03:28.777
5 B q1 2016-10-03 10:04:20.920
6 A tr 2016-10-03 10:04:48.533
7 A 1a 2016-09-30 10:36:26.287
In MySQL its an easy task - but with SQL Server all fields have to be contained in either an aggregate function or the GROUP BY clause. But that results in field combinations that does not exist.
Is there a way to handle this?
Thanks in advance!
Solution
Based on the comment from Andrew Deighton i did this:
SELECT *
FROM (
SELECT
id,
type_id,
some_value,
created_at,
ROW_NUMBER()
OVER (PARTITION BY type_id
ORDER BY created_at DESC) AS row
FROM test_sql
) AS ts
WHERE row = 1
ORDER BY row
Conclusion: No need for GROUP BY and DISTINCT.