customize query result - c#

I have 3 tables
tblIndividual
tblIndividualSpeciality
tblSpeciality
One individual have multiple speciality, when I write query I get many rows depends number of speciality to individual.
I need record in single row and each speciality have single column.
This is the table structure
My query
SELECT FirstName,LastName,SpecialtyName
FROM tblindividual ind,tblspecialty spec, tblindividualspecialty indspec
where
ind.pkIndividualID = indspec.fkIndividualID
and spec.SpecialtyCode = indspec.SpecialtyCode
and pkIndividualID = 355735;
I received this format as result
But I need this format as result
Can some one help me please.
I am using MySql database and development tool as Visual Studio 2013.

Part of your problem is that MySQL currently does not have the equivalent of SQL's PIVOT, and in overcoming that it also doesn't have a built-in concept of ROWNUM.
I created your tables with two separate individuals, four specialities of which the first Individual had 3 and the second had 2. I combined these into an interim table (temporary table if you prefer) using
INSERT INTO InterimResults
(
SELECT #row_number:=CASE WHEN #indId=pkIndividualId
THEN #row_number+1 ELSE 1 END AS row_number,
#indId:=pkIndividualId AS pkIndividualId, FirstName, LastName,
SpecialityName
FROM (SELECT #rownum:=0) n,
(SELECT #db_names:='') d,
(SELECT pkIndividualId,FirstName,LastName,SpecialityName
FROM tblindividual ind
inner join tblindividualspeciality indspec on ind.pkIndividualId=indspec.fkIndividualId
inner join tblspeciality spec on spec.pkSpecialityCode=indspec.fkSpecialityCode) r
);
This gave me the following results (with my test data). Note if you run this in SQLFiddle's "Build Schema" pane all of the row numbers come out as 1, but the query works correctly in the "Run Sql" panel.
row_number pkIndividualId FirstName LastName SpecialityName
1 1 Test I-Health Internal Medecine
2 1 Test I-Health Family Practise
3 1 Test I-Health Cardiology
1 2 Test2 J-Health Family Practise
2 2 Test2 J-Health Obstetrics
It is then quite simple to "pivot" this interim table using GROUP_CONCAT
SELECT
FirstName, LastName,
GROUP_CONCAT(if(row_number = 1, SpecialityName, NULL)) AS 'Speciality1',
GROUP_CONCAT(if(row_number = 2, SpecialityName, NULL)) AS 'Speciality2',
GROUP_CONCAT(if(row_number = 3, SpecialityName, NULL)) AS 'Speciality3'
FROM InterimResults
GROUP BY pkIndividualId;
References I used:
http://www.artfulsoftware.com/infotree/qrytip.php?id=78
and http://blog.sqlauthority.com/2014/03/09/mysql-reset-row-number-for-each-group-partition-by-row-number/
Of course this assumes that you only want to report on the first 3 specialities, or each individual can only have up to 3 specialities - if there are others then you will need to use Prepared statements and dynamic sql - there is an example at http://stratosprovatopoulos.com/web-development/mysql/pivot-table-with-dynamic-columns/

Use PIVOT query.
above link is for your reference.
http://forums.asp.net/t/1851916.aspx?Converting+Column+values+to+Rows+in+SQL+Query
This link is helpful for you.
I hope you solved your problem.

SELECT FirstName, LastName, SpecialtyName
FROM tblindividual T1,tblspecialty T2, tblindividualspecialty T3
WHERE T1.pkIndividualID = T3.fkIndividualID AND T2.SpecialtyCode =T3.SpecialtyCode AND pkIndividualID = 355735;

Related

Create complex query to execute queries stored in column?

I am trying to get some information from a table, when a (one or more than one) condition(s) is(are) met but this conditions are stored in other table.
Here is a screenshot of the 3 tables:
So I need a query to do this:
Given a Status (IDStatus) and an Action (IDAction)
If there is an IDCondition (it can be NULL, one, or more than one)
A. If there is one, use the IDocField as a column from a table called IDoc, using ConditionOperator as the condition (read this as =, <, >) and the value on ConditionValue.
B. If there are more than one, the same as before, but use each condition with AND.
C. If it is NULL, directly go to point 3
Get Subject, SendTo, CC, CCO, and FileTemplate that matched all of the above explained.
I want to try this because it would reduce my C# code, but if this is too complex or not plausible, I will do multiple queries like what I explained above.
I am asking this, because I am not sure how to get multiple conditions in a SELECT. I mean by this:
If there is more than one condition, how can I execute them or get all of them in a single query but that has all the returning things on point 3 ?
Example:
SELECT *
FROM WF_MailCondition
WHERE IDCondition = 1
this will return all conditions (keys can repeat) that has IDCondition equal to 1. But then I have to use all the three columns to create a condition like ID = 1 been ID in IDocField, = in ConditionOperator and 1 in ConditionValue.
I know there is some inconsistencies in the image, like IDCondition is NN (not null) but I said that it can be null (I am fixing this things).
My SQL:
SELECT
Subject, SendTo, CC, CCO, FileTemplate
FROM
WF_Mail AS M
INNER JOIN
WF_MailStatusAction AS S ON S.IDMail = M.IDMail
WHERE
(SELECT "HERE SELECT THE 3 COLUMNS TO USE A CONDITION" FROM WF_MailCondition WHERE IDCondition = S.IDCondition)
AND (S.IDAction = "ACTION FROM OUTSIDE" AND S.IDStatus = "STATUS FROM OUTSIDE")
How to do the SELECT "HERE SELECT 3 COLUMNS..." and if the IDCondition is NULL directly get the columns requested in the first SELECT (Subject, SendTo, etc.)
The "ACTION FROM OUTSIDE" is a parametrized statement.
Forget about foreign keys, we are not using it (boss' decisions...).
I am doing this because is for an "event" thing. I call a method in my C# code that will see if there are mails to send. But this mails can have none, one or more than one conditions. This is to have more options than all have to send a mail. Maybe in the workflow there is no need to send email but in code is "hardcoded" so with this I am totally free to do what I need about that feature.
Maybe all of this can be a function or a stored procedure but I am very ignorant about that and performance with them.
If you need more info, please tell me.
From what I understand, I would write a query like this:
select m.subject, m.cc
from wf_mail m
where exists (select 'true'
from wf_mailstatusaction s, wf_mailcondition c
where s.idmail=m.idmail
and s.idcondition = c.idcondition
and c.idocfield||c.conditionoperator||c.conditionValue = 'id>500'
group by s.idcondition
having count(s.idcondition) = 1)
or exists (select 'true'
from wf_mailstatusaction s, wf_mailcondition c
where s.idmail=m.idmail
and s.idcondition = c.idcondition
and c.idocfield||c.conditionoperator||c.conditionValue IN ('id>500', 'id<200')
group by s.idcondition
having count(s.idcondition) > 1)
or exists (select 'true'
from wf_mailstatusaction s
where s.idmail=m.idmail
and s.idcondition is null)
I would suggest the following:
- Create a QueryBuilder Class
Where you have methods like:
* AddSelect()
* AddFrom()
* AddWhere()
* ToString()
...
And then use the "middlelayer" to handle the query cunstruction based on the conditions
That way you have the most control over everything going on

select two columns from two different tables in the same db using mysql + use the output of query in C#

Dear Friends,
i want to select two columns from two different tables in the same db using mysql and set the output of the query to a variable in c#.
currently my code is as shown below:
MySqlCommand logcmdCheck = new MySqlCommand(query, connectionCheck);
string query = "SELECT DB.table1.column1,DB.table1.column2,DB.table2.column1,DB.table2.column2,DB.table2.column3 FROM DB.table1 WHERE DB.table1.column1=?x,DB.table2 WHERE DB.table2.column1=?y";
logcmdCheck.Parameters.AddWithValue("?x",UserName);
logcmdCheck.Parameters.AddWithValue("?y",emailID);
MySqlDataReader ldr = logcmdCheck.ExecuteReader();
A = ldr[0].ToString();
B = ldr[1].ToString();
C = ldr[2].ToString();
D = ldr[3].ToString();
E = ldr[4].ToString();
Error: Mysql query syntax is wrong.
Kindly please help me out with the mysql command to perform the requirement.
Thanks in advance
Suraj
You're going to have to use a SQL Join. Check it out here http://www.w3schools.com/sql/sql_join.asp. You need to have a foreign key in one of the tables that allows you to connect to the primary key of the other table. Every good database should be set up with tables that have foreign keys.
For example:
Table 1:
OrderNumber Name Order Total
1 John Smith 10.00
2 Sally Smith 5.00
3 Berry Jones 25.00
Table 2:
Item Number ItemTotal OrderNumber
1 5.00 1
2 5.00 1
3 2.50 2
4 2.50 2
5 25.00 3
In table 2 the OrderNumber is the foreign key that is able to join to table one. So your syntax would be:
SELECT * FROM table1 JOIN table2 ON table2.OrderNumber = table1.OrderNumber
That will give you one table which you can read from.

Selecting distinct column combinations from a DataTable object with another column as a condition, and some key information missing

This is quite related to a previous question that I asked and received a very good answer to - it's just gotten a bit more complicated now:
How can I select distinct column combinations from a DataTable object with another column as a condition?
I'm using C# 2010.
I have a DataTable object I'm working with which has the following structure (and is filled with sample data):
"name" "ID" "hiredate" "termdate"
Bobby 1 5/1/2011 7/1/2011
Peggy 2 5/1/2011
Lucy 4 7/3/2012
Jenny 3 5/2/2011
Jenny 3 5/2/2013
Jenny 3 5/2/2011 6/1/2011
Peggy 2 5/1/2011
Lucy 4 6/1/2012
I want to filter this DataTable to keep only distinct ("ID","hiredate") combinations. There are two main features of this problem: 1 - if there are duplicate ("ID","hiredate") entries, the one with the most information (i.e. an existing "termdate") should be kept. 2 - some entries don't have a "hiredate", and only a "termdate". They need to be matched up with the proper "hiredate" before condition 1 can be accurately handled (at least I think they do).
The data table is created from a csv and possibly added user input, not from a database query, otherwise my life would be a lot easier.
So the resulting table after doing this would be:
"name" "ID" "hiredate" "termdate"
Bobby 1 5/1/2011 7/1/2011
Peggy 2 5/1/2011
Jenny 3 5/2/2013
Jenny 3 5/2/2011 6/1/2011
Lucy 4 6/1/2012 7/3/2012
Jenny has two entries because she appeared with two different "hiredate" values, and one of them was also duplicated - the entry without the "termdate" was removed. Lucy's two rows have been merged - they had complementary missing dates.
Any suggestions for how to do this in C#? Again, I'm using a DataTable object. I still need to keep the "name" and "termdate" fields - if I didn't, then I was able to get a distinct ("ID","hiredate") list, but they really need to be retained.
In my original question, there were not any entries that had a "termdate" but no "hiredate", and this is was the accepted solution, which worked fine for me:
DataView dv = new DataView(dt);
dv.Sort = "ID ASC, HireDate DESC, TermDate DESC";
string lastID = "0";
List<DateTime> addedHireDatesForUser = new List<DateTime>();
foreach (DataRowView drv in dv)
{
if (drv["ID"].ToString() != lastID)
{
addedHireDatesForUser = new List<DateTime>();
addedHireDatesForUser.Add(DateTime.Parse(drv["HireDate"].ToString()));
// NEXT ID, ADD ROW TO NEW DATATABLE
}
else if (!addedHireDatesForUser.Contains(DateTime.Parse(drv["HireDate"].ToString())))
{
addedHireDatesForUser.Add(DateTime.Parse(drv["HireDate"].ToString());
// NEXT DATE, ADD ROW TO NEW DATATABLE
}
lastID = drv["ID"].ToString();
}
What I'm looking for is help with an (at least somewhat) elegant way to also deal with the entries missing "hiredate" as part of this process. I could write a really inefficient loop to match up all of them, but as there are (in reality) thousands of entries in this table, I have to wonder if there is a better way.
I appreciate any suggestions!
Does this have a SQL query attached to it? If so and the query is something like
SELECT name, ID, hiredate, termdate from table
It could be switched to
--First query returns combined record where they have a null in hiredate and one in termdate
SELECT t1.name, t1.ID, max(t2.hiredate) as hiredate, max(t1.termdate) as termdate from table t1
inner join table t2 on t1.id = t2.id and t1.hiredate is null and t2.hiredate is null
GROUP by t1.name, t1.ID
UNION
--Second query returns full records where both hiredate and termdate are there
SELECT name, ID, hiredate, termdate from table t1
where t1.hiredate is not null and termdate is not null
UNION
--Third query returns all records with a different hiredate that have no termdate and include them
SELECT name, ID, hiredate, termdate from table t1
LEFT OUTER JOIN t2 on t1.ID = t2.ID and t1.hiredate = t2.hiredate
where t1.termdate is null and t2.hiredate is null
This should cover all the situations you discussed.

Removing Duplicate row from a table based on one column

I created a table with multiple inner joins from 4 tables but the results brings back duplicate records. Here code that I am using
SELECT tblLoadStop.LoadID,
tblCustomer.CustomerID,
tblLoadMaster.BillingID,
tblLoadMaster.LoadID,
tblLoadMaster.PayBetween1,
LoadStopID,
tblLoadMaster.Paybetween2,
tblStopLocation.StopLocationID,
tblStopLocation.city,
tblStopLocation.state,
tblStopLocation.zipcode,
tblLoadSpecifications.LoadID,
tblLoadSpecifications.LoadSpecificationID,
Picks,
Stops,
Typeofshipment,
Weight,
LoadSpecClass,
Miles,
CommodityList,
OriginationCity,
OriginationState,
DestinationCity,
DestinationState,
LoadRate,
Status,
CompanyName,
Customerflag,
tblCustomer.CustomerID,
tblCustomer.AddressLine1,
tblCustomer.City,
tblCustomer.State,
tblCustomer.Zipcode,
CompanyPhoneNumber,
CompanyFaxNumber,
SCAC,
tblLoadMaster.Salesperson,
Change,
StopType
FROM tblLoadMaster
INNER JOIN tblLoadSpecifications
ON tblLoadSpecifications.LoadID = tblLoadMaster.LoadID
INNER JOIN tblLoadStop
ON tblLoadStop.LoadID = tblLoadMaster.LoadID
INNER JOIN tblStopLocation
ON tblStopLocation.StopLocationID = tblLoadStop.StopLocationID
INNER JOIN tblCustomer
ON tblCustomer.CustomerID = tblLoadMaster.CustomerID
WHERE tblLoadMaster.Phase LIKE '%2%'
ORDER BY tblLoadMaster.LoadID DESC;
This is the result that I get
Load ID Customer Salesperson Origin Destination Rate
-------------------------------------------------------------------------
13356 FedEx Alex Duluth New York 300
13356 FedEx Steve Florida Kansas 400
I only want the first row to show,
13356 FedEx Alex Duluth New York 300
and remove the bottom row,
13356 FedEx Steve Florida Kansas 400
The tblLoadStop Table has the duplicate record with a duplicate LoadID from tblloadMaster Table
One approach would be to use a CTE (Common Table Expression) if you're on SQL Server 2005 and newer (you aren't specific enough in that regard).
With this CTE, you can partition your data by some criteria - i.e. your LoadID - and have SQL Server number all your rows starting at 1 for each of those "partitions", ordered by some criteria (you're not very clear on how you decide which row to keep and which to ignore in your question).
So try something like this:
;WITH CTE AS
(
SELECT
LoadID, Customer, Salesperson, Origin, Destination, Rate,
RowNum = ROW_NUMBER() OVER(PARTITION BY LoadID ORDER BY tblLoadstopID ASC)
FROM
dbo.tblLoadMaster lm
......
WHERE
lm.Phase LIKE '%2%'
)
SELECT
LoadID, Customer, Salesperson, Origin, Destination, Rate
FROM
CTE
WHERE
RowNum = 1
Here, I am selecting only the "first" entry for each "partition" (i.e. for each LoadId) - ordered by some criteria (updated: order by tblLoadstopID - as you mentioned) you need to define in your CTE.
Does that approach what you're looking for??

Three-way join using one SQL table

Suppose there is a MSSQL table, UserPost, that represents something user has posted, with these fields:
ID | dateAdded | parentPostID | postBody
A user in the system could create a Request, receive a Response, and then other users could Comment on the Response. Ie, Request <=1:many=> Reponse <=1:many=> Comment (think StackOverlow's Question > Answer > Comment model-like).
All user posts (Request, Response and Comment) are represented by UserPost rows, where Request has parentPostID = null;; Responses' parentPostID is the Request's ID, and Comment's parentPostID is the ID of the Response.
I need to output everything in a simple fashion:
Request 1
- Response A
-- Comment (i)
-- Comment (ii)
- Response B
-- Comment (i)
Request 2
...
Question: which SQL statement returns the needed information in the most usable way?
I'm struggling to write a three-way join between (UserPosts) as Requests [join] (UserPosts) as Responses [join] (UsersPosts) as Comments but am not sure this is the easiest way.
Bonus: is it possible to do this using C# Linq?
Can't think of a way to do this in LINQ. I've removed unused columns. Luckily this is a bounded hierarchy. I'm using the new hierarchyid data type, which has the desired sort order:
create table UserPosts (
ID int not null,
ParentID int null
)
go
insert into UserPosts (ID,ParentID)
select 1,null union all
select 2,null union all
select 3,1 union all
select 4,2 union all
select 5,3 union all
select 6,1 union all
select 7,6
go
select
*
from
UserPosts up
left join
UserPosts up_1st
on
up.ParentID = up_1st.ID
left join
UserPosts up_2nd
on
up_1st.ParentID = up_2nd.ID
order by
CONVERT(hierarchyid,
COALESCE('/' + CONVERT(varchar(10),up_2nd.ID),'') +
COALESCE('/' + CONVERT(varchar(10),up_1st.ID),'') +
'/' + CONVERT(varchar(10),up.ID) + '/'
)
HierarchyIDs (as strings) look like /GrandParent/Parent/Child/ - so we construct values that look like this. Obviously, if we don't have a grandparent (up_2nd.ID is null, since we can't achieve 2 left joins as described), then we just want to construct /Parent/Child/ - this is what the 1st COALESCE is helping us achieve. Similarly, if we can't find any parents (both up_1st.ID and up_2nd.ID are null), then both of the COALESCEs just turn into empty strings, and we end up construcing /ID/.
You can add:
CASE
WHEN up_2nd.ID is not null then 'Comment'
WHEN up_1st.ID is not null then 'Response'
ELSE 'Request'
END as Level
to your select list, if you want to track what level the item is (or use numerics instead, if desired)

Categories