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

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.

Related

Order a 3 level object

I have this scheme
Document
DocumentId
Position
PositionId
DocumentId
Coordonate
CoordonateId
PositionId
Km
Road
RoadId
CoordonateId
Name
I need to order the documents by Road.Name and then by lowest Coordonate.Km. I tried to order them in SQL and EF but with no luck so now I use this code that is very slow:
foreach (var document in documents)
foreach (var position in documentPositions)
{
if (!position.Coordonates.Any())
continue;
var minKm =
position.Coordonates.OrderBy(a => a.Km).FirstOrDefault().Km.Value;
dictionary.Add(document, minKm);
break;
}
var sorted= dictionary.OrderBy(a => a.Key.RoadName).ThenBy(a => a.Value);
document.RoadName is a property that concatenates all the Road.Names that may be in the document.
LE:
I made a sqlfiddle at http://sqlfiddle.com/#!18/90b00/2/0 Hope that helps
You can write a subquery by Coordonates table, using rank function with windows function to get the samllest km, then do join
select Documents.DocumentId,
Documents.Name,
Roads.Name,
MIN(km) km
from Documents
INNER JOIN Positions ON Documents.DocumentId=Positions.DocumentId
INNER JOIN (
select
PositionId,
CoordonateId,
km,
rank() over(partition by PositionId order by Km) rn
from Coordonates
) Coordonates ON Positions.PositionId=Coordonates.PositionId and rn =1
INNER JOIN Roads ON Coordonates.CoordonateId=Roads.CoordonateId
group by Documents.DocumentId,
Documents.Name,
Roads.Name
Order By Roads.Name,km
[Results]:
| DocumentId | Name | Name | km |
|------------|------|------|----|
| 2 | Doc2 | A1 | 10 |
| 1 | Doc1 | A2 | 10 |
| 3 | Doc3 | A2 | 15 |
sqlfiddle
You can find min value without using OrderBy and then FirstOrDefault Instead use Min which should be a little bit faster.
var minKm = position.Coordinates.Min(coord => coord.Km.Value);
Update: maybe your code is slow because position.Coordinates is not loaded from the database and your code does extra database roundtrip for every document which is why it is slow. Please ensure all data is already loaded and the foreach loop is actually causing that slowness. If coordinates data aren't included you can add Include(...) statement into your EF query.

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.

Combining Characters with Id Field

I'll create an Issue table in an MVC5 application and I want to use special code for each type of the issues as below:
For IT related questions INF-0001, INF-0002, ...
For General type of questions GEN-0001, GEN-0002, ...
As I use all the issues on the same table, I think it is better to store the ID numbers as INF-0001, GEN-0001, ... etc. In that case should I use string as the data type of ID column in MSSQL? Or what is the best approach in order to store Id's with their related codes? I also think of using GUID, but I am not sure if it is possible. Thanks in advance.
I suppose it's better create separate field for your custom names. So your table will have int Id (Primary Key) field and CustomName varchar(100) or nvarchar(100) type (If you use unicode characters) field with your custom names.
It will be better for perfomance to use int as Id if you will JOIN your file table with others. If you want to search values in this field and it is slow just create INDEX.
You could have a general issue id and a category, for example:
Table: Issue
------------------------------------
IssueID | CategoryID | CategoryIndex
------------------------------------
1 | 1 | 1
2 | 1 | 2
3 | 2 | 1
4 | 1 | 3
Table: Category
-----------------------------
CategoryID | Prefix | Name
-----------------------------
1 | INF | IT
2 | GEN | General
Then you calculate the issue number when querying these tables.
You can store the calculated number in a table if you want to keep track of the issue number in case of a change in the database (ex: the prefix for IT related questions changes from INF to IT)
Now that you have a good schema, how do you keep control of the category sequence on the issues table? Check this out:
DECLARE #categoryID INT
DECLARE #nextSequence INT
SET #categoryID = 1 --You'll have to change this!
SELECT #nextSequence = i.CategoryIndex
FROM Issue i
WHERE i.CategoryID = #categoryID
SELECT COALESCE(#nextSequence, 0) + 1 as 'NextSequence'
You can turn that into a stored procedure (NextSequence, maybe?) that receives an INT as parameter (the category ID) and returns another INT as result (the CategoryIndex for the new issue).
Finally, to create your full code:
SELECT
i.IssueID
, c.Prefix + '-' + RIGHT('0000' + CONVERT(VARCHAR(4), i.CategoryIndex), 4) as 'IssueCode'
FROM Issue i
INNER JOIN Category c ON i.CategoryID = c.CategoryID

Selecting records with max version

I have a table as follows:
ConfigID | VersionNo | ObjectType
ConfigID and VersionNo constitute the unique key.
I want to be able to select the record with the highest VersionNo for each configID based on an object type.
I have tried
configs = (from config in configRepository.FindBy(x => x.ObjectType.Equals(typeof(Node).ToString(), StringComparison.InvariantCultureIgnoreCase))
group config by config.ConfigID into orderedConfigs
select orderedConfigs.OrderBy(x => x.ConfigID).ThenByDescending(x => x.VersionNo).First());
EDIT: I must add that the FindBy is basically just a where clause.
But I am getting no results. Please help me with this.
EDIT:
The data in the table could look like:
3fa1e32a-e341-46fd-885d-8f06ad0caf2e | 1 | Sybrin10.Common.DTO.Node
3fa1e32a-e341-46fd-885d-8f06ad0caf2e | 2 | Sybrin10.Common.DTO.Node
51d2a6c7-292d-42fc-ae64-acd238d26ccf | 3 | Sybrin10.Common.DTO.Node
51d2a6c7-292d-42fc-ae64-acd238d26ccf | 4 | Sybrin10.Common.DTO.Node
8dbf7a33-441f-40bc-b594-e34c5a2c3f51 | 1 | Some Other Type
91413e73-4997-4643-b7d2-e4c208163c0d | 1 | Some Other Type
From this I would only want to retrieve the second and fourth records as they have the highest version numbers for the configID and are of the required type.
Not sure if 100% works because writing out of VS :) but idea should be good
var configs = configRepository.Where(x=>x.ObjectType==typeof(Node).ToString());
var grouped = configs.GroupBy(x=>x.ConfigId);
var a = grouped.select(x=>x.OrderByDescending(y=>y.VersionNo).First());
It looks LINQ sql to but in pure SQL i can write the query like this
SELECT ConfigID ,MAX(VersionNo ) FROM CUSTOMIZE_COLUMNS_DETAIL WHERE
ObjectType = 'objectType' GROUP BY ConfigID
I have tried to replicate the scenario in sql , might by useful to you, THanks

Union on muliple tables in C#

I am using C# and trying to do union on multiple datatables in the code.
Table 1
ID | Value | Value2
-----------------
1 | Tom | Null
-----------------
2 | John | Null
-----------------
...
Table 2
ID | Value | Value2
-----------------
1 | Null | Susie
-----------------
2 | Null | Kim
-----------------
...
And, I want the result table would be something like
TableResult
ID | Value | Value2
-----------------
1 | Tom | Susie
-----------------
2 | John | Kim
-----------------
...
Is there a way I could this?
I'm not sure what datastructure you are using in C#, but you can do this right in your database:
SELECT COALESCE(Table1.ID, Table2.ID) AS ID
,COALESCE(Table1.Value, Table2.Value) AS Value
,COALESCE(Table1.Value2, Table2.Value2) AS Value2
FROM Table1
FULL OUTER JOIN Table2
ON Table1.ID = Table2.ID
I chose a FULL OUTER JOIN here so that items could be missing on EITHER side (I generally expect most people will use a FULL OUTER JOIN about once a year in their careers), as well as an arbitrary choice to always pick the value in Table1 if it existed first, so Table2 would not overwrite something in Table1.
So as an example of how the FOJ works:
Table 1
1,A,NULL
2,B,X
3,NULL,Y
4,D,Z
Table 2
1,NULL,P
2,NULL,Q
3,C,NULL
5,E,W
Output:
1,A,P
2,B,X
3,C,Y
4,D,Z
5,E,W
If they're already in DataTables, you could load them into another table:
DataTable unionTable = new DataTable();
unionTable.Load(table1.CreateDataReader());
unionTable.Load(table2.CreateDataReader());
I think the notion of doing it server side as previously mentioned is a lot better approach though...
Another way to do this in Linq
//Lets say you have two tables (fill the variables from dababase)
IQueryable tab1 = new List().AsQueryable();
IQueryable tab2 = new List().AsQueryable();
//You can create Result table this way
var resultTable = tab1.Select(t1 => new Table1 { t1.ID, t1.Value, tab2.Any(t2 => t2.ID == t1.ID) ? tab2.First(t2 => t2.ID == t1.ID).Value : null });

Categories

Resources