I am working on a C# application that uses a database. I need to join two tables together, but they are linked strangely. One table has letters identifying the data like A, B, C, etc. and the other has string values identifying the type like "small" or "large"
I need to join the tables so that the values in the first table's column with the code 'a' link to the other table's column with the value of "small" and the values that are 'b' or 'd' link to the other table's value of "large"
What is the best way to do this using standard SQL. Is there some way I can have extra conditionals in the join statement or is it best to do something like this in a where clause?
Thanks,
-Jake
The easiest method to handle this would be to have an intermediate table that maps the the values. You can then add this table to your statement and use it join the main tables together.
Make a case statement to map a to 'small' and b,c,d... to 'Large' in your first table,with the new field join the tables
Make an intermediate table or query.
SELECT *
FROM (
SELECT CASE col WHEN 'A' THEN 'small'
WHEN 'B' THEN 'large'
WHEN 'D' THEN 'large'
ELSE NULL
END AS col
FROM one
) x
JOIN two t
ON x.col = t.col
http://sqlfiddle.com/#!6/45eb0/1
Based on your description, I think you can use Common table expression , to select those values you need , as well as the column which has A,B,C values. Then use CTE to join your second table. it will looks like the following.
;WITH A_CTE (columns)
AS
(
select column1,columnb, CASE A_B_C_COLUMN WHEN 'A' THEN 'LARGE' WHEN 'B' THEN 'SMALL' WHEN 'C' THEN 'TINY' END AS ColumnC
)
select * from A_CTE JOIN TABLEB ON A_CTE.ColumnC = TABLEB.ConditionColumn
if you can provide more detail, happy to write the SQL Statement for you.
Related
I would like to join on a large list of integers in SQL Server instead of a big IN clause.
My query :
SELECT
mmr.idContact,
mmR.idQuestion as IdQuestion,
MIN(mmR.idResponse) AS IdResponse
FROM MatchResponses mmR
--JOIN Contact c on c.idContact = mmR.idContact //to show the linked ids
JOIN Contact c on c.idSpecific in (1,2,3...10000)
WHERE myId= 300
GROUP By mmR.idContact, mmr.idQuestion
order by idContact, idQuestion
The IN clause is way too long, I can join mmR and COntact with an idContact.
The query takes 44s I would like to make it shorter using a JOIN
How can I declare the integers table "on the go" ?
My idea would be to handle the integer table using a temporary table in SQL. If you know the lower and upper limit of the integer table, it is easy to generate a temp_table in SQL and use it as a sub query with "In" Clause. It will not affect much on query performance.
Better to handle these from the DB rather than using an intermediate code to such as C# unless it is the requirement.
If you can attach sample schema and data, I can provide the code for you.
Thanks for all, I reseigned myself to simply not use the join or anything, no filter. The filtering wasn't more efficient, I after used LinQ (I only had 200 rows)
For the people looking for a solution :
I could have inserted all of the id in a temp table be careful you can't insert more than 1000 rows so use this trick:
DECLARE #tempTable TABLE (id INT)
INSERT INTO #EMPLOYEEDETAILS(id)
SELECT * FROM (VALUES
(1),(2),
.....
(10000)
) A(Col1)
And then the JOIN :
SELECT
mmr.idContact,
mmR.idQuestion as IdQuestion,
MIN(mmR.idResponse) AS IdResponse
FROM MatchResponses mmR
JOIN Contact c on c.idContact = mmR.idContact
JOIN #tempTable con on con.id = c.idSpecific
WHERE myId= 300
GROUP By mmR.idContact, mmr.idQuestion
order by idContact, idQuestion
I have a query like this:
Select table1.*, table2.column1 from table1 join table2 on table1.column1=table2.column1
It works, but it puts the column in the end of the datagridview, but i have to put table2.column1, after a specified column of table2, and i have to use table1.* and i cant use listing of the table1's columns is it possible?
And why exactly can't you use a list of all the fields?
NO , it's not possible to place a column in the middle of columns specified with * , not with pure SQL and not with dynamic.
Just specify them, don't be lazy, it's better practice:
SELECT table1.col1,
table1.col2,
table2.col1,
table1.col3
..........
because i am using union queries, and the table names are changing and one table contains more colums than the other
if table1 differs, that above all should be a strong argument for specifing all needed fields separatly. In case of a new field in table1, your query would be broken, cause the number of fields will differ from the ones used in the next union.
I need some help wrapping my head around doing the following.
I have a predefined list if ID numbers, we'll call them Alias, which I get from a CSV file. What I'm trying to do is compare that list to my database and find which ones exist in the CSV but NOT in the SQL database.
First thing is I'm unsure as to how to define a list of say 1,2,3,4,5 as a table with the column name as Alias so that I can join / select from that.
Secondly, how would you go about writing this query? I was thinking of having to structure it something like the following:
SELECT * FROM (1,2,3,4,5) WHERE Alias NOT IN (
SELECT Alias FROM table1 WHERE Alias IN (1,2,3,4,5));
I'm aware that this query wouldn't work, think of it more like pseudo-code, but even if something like that were to work, writing out that list twice could prove to be troublesome (I can have upwards of 50K alias' in the list) and most likely horribly inefficient.
Thanks for any advice!
After a coffee and a quick break I think I have the best solution.
Considering this is going to be a stored procedure anyway, the stored procedure will take the following action.
Create TempTable IF NOT EXISTS, TRUNCATE if it does
INSERT (CSVList) INTO TempTable
SELECT Alias FROM TempTable WHERE Alias NOT IN (SELECT Alias FROM MainTable)
This way I can specify that list as a table and select from it only once :)
Suppose you have your CSV values (comma separated) in T table, and T1 is your MainTable. Then following is the code that may help you. And this SQLFiddle that I tried.
Stage 1: Make your horizontal comma separated data into column data.
SELECT
Split.a.value('.', 'VARCHAR(100)') AS data
FROM (SELECT
CAST ('<M>' + REPLACE([id], ',', '</M><M>') + '</M>' AS XML) AS String
FROM T) AS A CROSS APPLY String.nodes ('/M') AS Split(a)
Here T is your table and id is the column name that has comma separated data.
Stage 2: Now merge this query with your main table to get the result.
select * from
(SELECT
Split.a.value('.', 'VARCHAR(100)') AS data
FROM (SELECT
CAST ('<M>' + REPLACE([id], ',', '</M><M>') + '</M>' AS XML) AS String
FROM T) AS A CROSS APPLY String.nodes ('/M') AS Split(a)) as CSV
where data not in (select * from T1)
For performance and efficiency, please use NOT EXISTS in comparing the 2 table outputs.
Something like this:
SELECT * FROM Tbl1 t1 WHERE NOT EXISTS (SELECT * FROM Tbl2 t2 WHERE t2.Col1 = t1.Col1)
I have a DataSet that contains two tables. One is considered to be nested in the other.. All I want is for it to not be nested and for there to be one table. .Merge() and LINQ just aren't doing the trick.
Here is a sample of what the main table would look like
student-id ID
--------------------
123456789 1
654987321 2
But each of these has multiple rows that they correspond to in the next table
ID Col1 Col2 etc.
----------------------
1 fact1 fact2
1 fact3 fact4
2 fact5 fact6
I want to combine them so they would look like this...
student-id Col1 Col2
-------------------------------
123456789 fact1 fact2
123456789 fact3 fact4
654987321 fact5 fact6
Everytime that I try the merge it doesn't work I get an error that I cant duplicate the primary key which is "ID" and since the merge is based on the primary key(i believe) I cant remove it.
I cant use LINQ because I want to make this generic so that the second table could have any number of columns and I cant get the select to work for that.
UPDATE: MY SOLUTION
I ended up cloning the second table to a new data table. Then adding a column called 'student-id' and deleting the ID column. The I looped through the rows of the Main table finding and related them to row in the second table... Combined all the data in an array and created a row in the final table.
The LINQ isn't as bad as you suggest. You can just use an anonymous type that holds two DataRows:
var result = from t1 in table1.AsEnumerable()
join t2 in table2.AsEnumerable() on (int)t1["ID"] equals (int)t2["ID"]
select new
{
Student = t1,
Facts = t2
};
foreach(var s in result)
Console.WriteLine("{0} {1} {2}", s.Student["student-id"], s.Facts["Col1"], s.Facts["Col2"]);
That way, you're not including specific columns in your output, so you can access them after the fact.
That being said, the other poster's suggestion of using a pivot table is probably a better direction to go.
let's try it in SQL.
Let, 1st Table = Table1 and 2nd Table = Table2
SQL:
Select
X.student-id,Y.Col1,Y.Col2
From Table1 As X Inner Join Table2 As Y On Y.ID=X.ID
I think if you try it in SQL it's easy to do!!!
Sounds like what you need is a Pivot table.
This will essentially allow you to display the data how you want.
Here are a couple of tutorials/projects
http://www.codeproject.com/Articles/25167/Simple-Advanced-Pivots-with-C-and-ASP-NET
http://www.codeproject.com/Articles/46486/Pivoting-DataTable-Simplified
Update
you may find yourself better doing the 'pivot' part in MS SQL as stored procedure and then populating your datatable with the results of calling this stored procedure. This example here is a great starting block
http://blogs.msdn.com/b/spike/archive/2009/03/03/pivot-tables-in-sql-server-a-simple-sample.aspx
I'm using SQL Server 2000, and given a a set of data (with unique ID's), I want to figure out the diffs with rows in the database, matching on the unique IDs. I'm also trying to keep it as flexible as possible.
I can use C#/VB in the front end to take the parameters, or even return things. Maybe passing in XML and getting XML in return?
For example, I want a function that calls:
// returns the columns that are different
func( A, B, C ) {
}
Any ideas?
There's a cool trick you can use with UNION:
SELECT MAX(tbl) AS TABLE_NAME, unique_key
FROM (
SELECT 'table1' AS tbl, unique_key
FROM table1
UNION ALL
SELECT 'table2' AS tbl, unique_key
FROM table2
) AS X GROUP BY unique_key
HAVING COUNT(*) = 1
This will show where one side or the other has rows which the other doesn't have.
This can be expanded to do more, obviously.
Alternatively, you can do an INNER JOIN (matches on keys where data is different), LEFT JOIN (key missing on one side) and RIGHT JOIN (key missing on the other) and UNION them all together.
I actually have a utility SP (it uses one or the other method depending on what options you need) which will compare any two tables and has options for setting which columns are considered the part of keys, which columns to ignore, restrict each side to a subset, etc. It even has an option to write the differences to a table.
I'd go with an existing "data diff" tool like
Red-Gate SQL Data Compare
ApexSQL Data Diff
Marc
Yeah agree with Marc, a specialized tool works best, something like Volpet Table Diff for SQL Server