Sql query with complex joins - c#

I am developing c# application.
I am using OLEDB connections.
I have following two tables>>
payment
AdmissionNumber | StudName |
1 John
2 Smith
paymentDetails
AdmissionNumber | RemainingFee | Date | Payment
1 5000 10/10/2012 3000
1 3000 10/11/2012 2000
2 4000 15/11/2012 3000
1 1000 10/12/2012 2000
In this I want to get the table result as following>>
AdmissionNumber | Name | Date |RemainingPayment|Payment|
1 John 10/12/2012 1000 2000
In this case Admission number and date is already provided in the form via textbox and datetimepicker.

In this case Admission number and date is already provided in the form
via textbox and datetimepicker.
So you want to search for a specific Admission number and a date. If so, then try this:
SELECT
p.AdmissionNumber,
p.Name,
pd.Date,
pd.RemaingFee AS RemainingPayment,
pd.Payment
FROM Payment p
INNER JOIN PaymentDetails pd ON p.AdmissionNumber = pd.AdmissionNumber
WHERE p.AdmissionNumber = #AdmissionNumberParamFromTxtBox
AND pd.Date = #DateParamFromTheotherTextBox;

This will give you the exact result. Matching between master and the last record of the details. You should have an Primary key column in the details.
Select *
From Payment
Left Outer Join
PaymentDetail
On PaymentDetail.Id = (
Select Top 1
A.Id
From PaymentDetail As A
Where A.AdmissionNumber = Payment.AdmissionNumber
Order By A.Date Desc
)
Cheers

SELECT
p.AdmissionNumber,
p.Name,
MAX(pd.Date) AS Date,
pd.RemaingFee AS RemainingPayment,
pd.Payment
FROM Payment p
INNER JOIN PaymentDetails pd ON p.AdmissionNumber = pd.AdmissionNumber
GROUP BY p.AdmissionNumber,pd.Payment,p.Name,pd.RemaingFee

Related

Select Customer ID with Condition From Customer Table and Count all log placed using Log table- SQL

I have two table as defined below,
Table: Customer:
ID | Customer_Name |Sex (bit)
--------------------------
1 | John | men
2 | Mack |women
3 | Andy |women
Table: Log:
ID | Customer_ID| Date
--------------------------
1 | 1 | 2020-06-03
2 | 3 |2020-06-03
I want to write a query to select each name with Sex condition and count of all Log placed by each customer using JOIN. the result will be,
1 | 1
2 | 0
3 | 0
My query:
(SELECT Customer.ID, COUNT(Log.Customer_ID) as number
from
Customer
Left JOIN
Log
on
Customer.Sex=0 and
Customer.ID=Log.Customer_ID
and
Log.Date>='2020-06-13'
group by Customer.ID)
But its returning incorrect results. Please advise
Use conditional aggregation
SELECT Customer.ID, COUNT(case Customer.Sex when 0 then Log.Customer_ID end) as number
from
Customer
Left JOIN
Log
on
Customer.ID=Log.Customer_ID
and
Log.Date>='2020-06-13'
group by Customer.ID
If you need only men/women move the predicate to WHERE
select Customer.ID, COUNT(Log.Customer_ID) as number
from Customer
left join Log
on Customer.ID=Log.Customer_ID
and Log.Date>='2020-06-13'
where Customer.Sex = 0
group by Customer.ID
Can you show the results this query is returning?
I think left join isn't a good approach, I would try with inner join instead if you want to filter in on clause (or just use where).
(SELECT Customer.ID, COUNT(Log.Customer_ID) as number
from Customer
JOIN Log on Customer.Sex=0 and Customer.ID=Log.Customer_ID and Log.Date>='2020-06-13'
group by Customer.ID)

C# DataSet Designer - AccesDB - Combine two rows into one

I need your help with an SQL query, that I am trying to build in C# Dataset Query Builder...
SELECT HouseHold.HHID, Client.FIRST_NAME, Client.LAST_NAME
FROM ((Client
INNER JOIN HouseHold_Client ON Client.CID = HouseHold_Client.CID)
INNER JOIN HouseHold ON HouseHold_Client.HHID = HouseHold.HHID)
Above code gives me the list of all HouseHolds (their ID) with Clients belonging to them:
HHID | FIRST_NAME | LAST_NAME
------------------------------
1 | Penelope | Grant
1 | Brian | Dyer
2 | James | Newman
2 | Richard | Parsons
.. but I can't figure out how to get people belonging to same HouseHold to show up on the same line, like this for a Data Grid View later on:
HHID | I_FIRST_NAME | I_LAST_NAME | II_FIRST_NAME | II_LAST_NAME
-----------------------------------------------------------------
1 | Penelope | Grant | Brian | Dyer
2 | James | Newman | Richard | Parsons
I have found loads of very similar questions, but very few had the same exact problem to solve. The ones (one or two) that really had the same problem and it had a solution, I just couldn't twist around my problem.
Any help is very much appreciated...
Thank you very much,
AD
Since you have only 2 persons per household, you can use the trick to get the minimum and maximum client Id per household. This is done in a subquery.
SELECT
X.HHID,
C1.FIRST_NAME AS I_FIRST_NAME, C1.LAST_NAME AS I_LAST_NAME,
C2.FIRST_NAME AS II_FIRST_NAME, C2.LAST_NAME AS II_LAST_NAME
FROM
(( SELECT
HHID, Min(CID) AS MinCId, IIf(Max(CID)=Min(CID), Null, Max(CID)) AS MaxCId
FROM HouseHold_Client
GROUP BY HHID
) X
INNER JOIN Client AS C1
ON X.MinCId = C1.CID)
LEFT JOIN Client AS C2
ON X.MaxCId = C2.CID;
The purpose of the IIf() expression is to output the maximum client Id only if it is different from the minimum client Id. To also return a record when MaxCId is Null, a LEFT JOIN is required on C2.
I did not join the HouseHold table here, since we only need the HHID from it, which is also available in HouseHold_Client. You can of course join it as well, if you need other columns from it.
Subquery:
( SELECT
HHID, Min(CID) AS MinCId, IIf(Max(CID)=Min(CID), Null, Max(CID)) AS MaxCId
FROM HouseHold_Client
GROUP BY HHID
) X
Subqueries must be enclosed in parentheses and be given a name (here X). X acts as a normal table having the columns HHID, MinCId and MaxCId in the main query. It is grouped by HHID. I.e., it returns one row per HHID. Min(CID) returns the smallest CID and Max(CID) largest CID per HHID.
In the case where you have 2 clients per HHID, this means that Min and Max will yield these 2 clients. If you have only 1 client, then both Min and Max will return the same client. If this is the case, then the IIf will return Null instead of Max(CID) to avoid returning twice the same client.

Get last purchase along with price

I want to get the Catalog of a selected supplier along with the last purchase price which is the column Costs in the CommandDetails table as shown bellow :
Product (idproduct, productName)
Command (idCommand, CommandCode, CommandDate, idSupplier)
CommandDetails(idCommandDetails, idProduct, Qty, idCommand, Costs)
Supplier (idSupplier, SupplierName, SupplierAddress)
SupplierCatalog (idSupplier, idProduct)
I tried the row_number() Over (Partition by ...) and other methods but i'm missing something, my brain said enough.
Desired Result :
--------------------------------------------------
| SupplierName| ProductName | CommandDate | Costs|
--------------------------------------------------
| SUP1 | P1 | 01/01/2018 | 3,06 |
| SUP1 | P6 | 01/01/2018 | 1,65 |
| SUP1 | P8 | 03/01/2018 | 5,20 |
| SUP1 | P9 | 05/01/2018 | 8,00 |
| SUP1 | P10 | 01/01/2018 | NULL |
--------------------------------------------------
Null in Costs for P10 when the product has never been ordered.
My last attempt :
SELECT
*
FROM
(SELECT
Sct.idsupplier,
SCt.idProduct,
SCD.PurchasePriceCmd Costs,
SCD.Qty,
P.ProCode,
P.ProName,
Row_number() OVER(PARTITION BY Sct.idProduct order by P.ProCode) rn
FROM SupplierCatalog SCt
LEFT JOIN CommandDetails SCD
ON SCD.idProduct = SCat.idProduct
LEFT JOIN Command a
ON a.idCommand = SCD.idCommand
LEFT OUTER JOIN StoreCommand b
ON a.idCommand = b.idCommand
INNER JOIN Product P
ON P.idProduct = SCt.idProduct) t
where Sct.idSupplier = 4 and rn = 1
You could also try this:
SELECT
s.supplierName,
p.productName,
latestCommandDetail.CommandDate,
latestCommandDetail.Costs
FROM Supplier s
INNER JOIN SupplierCatalog sc ON sc.idSupplier = s.idSupplier
INNER JOIN Product p ON p.idProduct = sc.idProduct
OUTER APPLY
(
SELECT TOP 1
c.CommandDate,
cd.Costs
FROM Command c
INNER JOIN CommandDetails cd ON cd.idCommand = c.idCommand
WHERE c.idSupplier = s.idSupplier AND cd.idProduct = p.idProduct
ORDER BY c.CommandDate DESC
) latestCommandDetail
WHERE s.idSupplier = 4
ORDER BY
s.supplierName,
p.productName
I don't have SQL Server going on this machine at the moment so you may need to tweak the syntax. The trick is just doing a link to a subquery that returns the top row sorted by the date descending.
I'm assuming the idSupplier for "SUP1" is 4 as per you example code above.
OUTER APPLY (the other optional join) will return nulls if no record is returned from the sub query. If you are only interested in products with prices use CROSS APPLY instead.
Also note that this query does not determine what to do if:
- there are two Commands for the same last date from the same supplier for the same product but with different Costs
- the same product is sold twice under the same Command but at different Costs
In both cases this can probably be handled by extending the sort order of the sub-query or by grouping/aggregating the sub-query.
Something like this ought to work:
;with cte as (
select a.idCommand, b.idProduct, row_number() over (partition by b.idProduct
order by a.CommandDate desc) as rn, a.CommandDate, b.Costs
from Command a
inner join CommandDetails b on a.idCommand = b.idCommand
)
select
c.SupplierName, e.productName, cte.CommandDate, cte.Costs
from Supplier c
left join SupplierCatalog d on c.idSupplier = d.idSupplier
left join Product e on d.idProduct = e.idproduct
left join cte on e.idProduct = cte.idproduct and cte.rn = 1
where c.idSupplier = #SupplierNumber;
You can probably replace the common table expression at the top with a subquery, or take some fields out of the CTE and join them in later.

View and Combine 2 rows in 1 from same table

I have a problem to view my data as I want,
IDFlight | Dep1 | Des1| Date | IDFlight2 | Dep2 | Des2 | Date | Price
---------+------+-----+-------+-----------+------+------+--------+--------
2 | AYT | PRN |20.3.15| 3 | PRN | AYT | 27.3.15| 150
2 | AYT | PRN |20.3.15| 4 | PRN | AYT | 30.3.15| 150
1 | AYT | PRN |23.3.15| 4 | PRN | AYT | 30.3.15| 150
1 | AYT | PRN |17.3.15| 3 | PRN | AYT | 27.3.15| 150
So search query was with Dates +- 3 days both for 2 flights.
in my case every flight is registered alone in table Flights, each flight has his flight number and his direction, date and pricing(e.g return and one way).
now the problem here is, when user selects the return option, there will be displayed 2 flights in one row, (flight 1 go to destination, flight 2 return from destination) also there is a differences between dates line in the example in the picture.
what I am trying to achieve is displaying data like in example above , that every "one way " record should match with the " return " record. even if the first data is repeated.
I have done a lot of research but no result,
also I tried to do with a view but no success
I tried union no success.
#prmDepDay int, #prmDesDay int, #prmDateDep datetime, #prmFrom int, #prmTo int,
#prmDateRe datetime, #prmFromRe int, #prmToRe int, #prmTotalRe int
AS
BEGIN
DROP TABLE departureflights
SELECT TOP(100) PERCENT
t_flights.idflight,
t_flights.flightnumber,
t_departureairport.depairportname,
t_destinationairport.desairportname,
t_flights.startdate,
t_flights.totalseats
INTO departureflights
FROM t_flights
INNER JOIN t_departureairport
ON t_flights.iddepartureairport = t_departureairport.iddepartureairport
INNER JOIN t_destinationairport
ON t_flights.iddestinationairport = t_destinationairport.iddestinationairport
INNER JOIN t_flightdirections
ON t_flights.iddirection = t_flightdirections.iddirection
WHERE t_departureairport.iddepartureairport = #prmFrom
AND t_destinationairport.iddestinationairport = #prmTo
AND startdate >= Dateadd(day,-#prmDepDay,#prmDateDep)
AND startdate <= Dateadd(day,#prmDepDay,#prmDateDep)
--and TotalSeats>= #prmTotal
ORDER BY t_flights.startdate
DROP TABLE returnflights
SELECT t_flights.idflight,
t_flights.flightnumber AS ReFlightNumber,
t_departureairport.depairportname AS ReDepAirportName,
t_destinationairport.desairportname AS ReDesAirportName,
t_flights.enddate ,
t_flights.totalseats
INTO returnflights
FROM t_flights
INNER JOIN t_departureairport
ON t_flights.iddepartureairport = t_departureairport.iddepartureairport
INNER JOIN t_destinationairport
ON t_flights.iddestinationairport = t_destinationairport.iddestinationairport
INNER JOIN t_flightdirections
ON t_flights.iddirection = t_flightdirections.iddirection
WHERE t_departureairport.iddepartureairport = #prmFromRe
AND t_destinationairport.iddestinationairport = #prmToRe
AND enddate >= Dateadd(day,-#prmDesDay,#prmDateRe)
AND enddate <= Dateadd(day,#prmDesDay,#prmDateRe)
AND totalseats>= #prmTotalRe
ORDER BY t_flights.enddate
If you join the t_flights table with itself you should get both the outgoing and returning flight info in one row.
SELECT journey_out.idflight IDFlight,
journey_out.iddepartureairport Dep1,
journey_out.iddestinationairport Des1,
journey_out.enddate Date1,
journey_return.idflight IDFlight2,
journey_return.iddepartureairport Dep2,
journey_return.iddestinationairport Dep2,
journey_return.enddate Date2
FROM t_flights journey_out
INNER JOIN t_flights journey_return
ON journey_out.iddestinationairport = journey_return.iddepartureairport
AND journey_out.enddate < journey_return.startdate
ORDER BY journey_out.startdate
The first join condition makes sure that the flight is going home from the correct airport, and the second condition makes sure that the return journey does not start before the arrival.
If you want to see the one way options in the same result set as the return options you can change it to a LEFT JOIN instead of an INNER JOIN.

how to get only those which have maximum value in a specified column in asp.net c#

I have a table with "customer_id, date, installment_no, amount" columns. I want to get the information of last installment of each customer_id till today. here installment_no is int type and when a new installment is deposited, the installment_no is increased by 1 in new entry. My table look like:
CS1001 | 12-06-2013 | 1 | 2500
CS1002 | 19-06-2013 | 1 | 1600
CS1001 | 14-07-2013 | 2 | 2500
I want to get a sqlcommand statement for do so.
Group all records by customer_id, then order all customer's records by installment_no, and select only record with max installment_no from each group:
from c in customers
group c by c.customer_id into g
select g.OrderByDescending(x => x.installment_no).First()
Same with pure SQL if you don't use Linq
SELECT c.* FROM Customers c
INNER JOIN (
SELECT customer_id, MAX(installment_no) max_installment
FROM Customers
GROUP BY customer_id
) cmax
ON c.customer_id = cmax.customer_id
AND c.installment_no = cmax.max_installment
var result = list.GroupBy(x=>x.customer_id)
.Select(g=>g.OrderByDescending(y=>y.installment_no).First())
.ToList();

Categories

Resources