Dynamic sql join in sql server - sql-server-2005

I have a relationship between two tables. The two tables PKs are int types.
In one table (UserS), I need to supply the Username and get the corresponding ID (which is the PK). This is the standard ASP.NET user table when using forms authentication.
However, in a related table, I want to supply the ID I find from the Users table to get a value out.
Something like:
Run query to get ID for a username (simple select/where query)
Return the result
Run a subquery where I can pass in the above result -
Get value where ID = result
This sounds a lot like dynamic sql. However, there might be a better suited and appropriate way of writing this query (on Sql Server 2k5).
How can I go about doing this and what gotchas lurk?
EDIT: I will try something along the lines of http://www.sqlteam.com/article/introduction-to-dynamic-sql-part-1
EDIT: Thanks for the tips everyone, I wrote this:
SELECT Discount.DiscountAmount
FROM Discount
INNER JOIN aspnet_Users
ON Discount.DiscountCode = aspnet_Users.UserId And aspnet_Users.Username = 's'
Where 's' is to be replaced by a parameter.
Thanks

You don't have to use dynamic SQL for that.
You can use a lookup instead:
DECLARE #ID bigint
SELECT #ID = ID FROM Users WHERE Username = #Username
SELECT
*
FROM
TableB
WHERE
ID = #ID
Then, you could add the PARAMETER #Username to your SqlCommand object, preventing the risks of SQL Injection.
Also, doing the lookup is preferable to a join, since the index is scanned a single time, for TableB.

Right, i just would do this:
SELECT *
FROM TableB
JOIN Users ON Users.Id = TableB.ID
WHERE Users.Username = #Username

Regarding lookup vs joins - while it may seem more intuitive for the novice to use the lookup, you should go with a join. A lookup needs to be evaluated for every row in your primary result set, while a join is evaluated once. Joins are much more efficient, which means that they are faster.

This is just a simple join isn't it?
SELECT x.*
FROM user_table u
INNER JOIN
other_table x
ON u.id = x.user_id
WHERE u.name = #user_name

SELECT values.value
FROM form_users, values
WHERE form_users.username = 'John Doe'
AND values.user = form_users.userid

SELECT
*
FROM
table2 t2
JOIN
UserS t1 ON t2.IDKey = t1.IDKey
WHERE
UserS.Username = #Input

Related

Check the query efficiency

I have this below SQL query that I want to get an opinion on whether I can improve it using Temp Tables or something else or is this good enough? So basically I am just feeding the result set from inner query to the outer one.
SELECT S.SolutionID
,S.SolutionName
,S.Enabled
FROM dbo.Solution S
WHERE s.SolutionID IN (
SELECT DISTINCT sf.SolutionID
FROM dbo.SolutionToFeature sf
WHERE sf.SolutionToFeatureID IN (
SELECT sfg.SolutionToFeatureID
FROM dbo.SolutionFeatureToUsergroup SFG
WHERE sfg.UsergroupID IN (
SELECT UG.UsergroupID
FROM dbo.Usergroup UG
WHERE ug.SiteID = #SiteID
)
)
)
It's going to depend largely on the indexes you have on those tables. Since you are only selecting data out of the Solution table, you can put everything else in an exists clause, do some proper joins, and it should perform better.
The exists clause will allow you to remove the distinct you have on the SolutionToFeature table. Distinct will cause a performance hit because it is basically creating a temp table behind the scenes to do the comparison on whether or not the record is unique against the rest of the result set. You take a pretty big hit as your tables grow.
It will look something similar to what I have below, but without sample data or anything I can't tell if it's exactly right.
Select S.SolutionID, S.SolutionName, S.Enabled
From dbo.Solutin S
Where Exists (
select 1
from dbo.SolutionToFeature sf
Inner Join dbo.SolutionToFeatureTousergroup SFG on sf.SolutionToFeatureID = SFG.SolutionToFeatureID
Inner Join dbo.UserGroup UG on sfg.UserGroupID = UG.UserGroupID
Where S.SolutionID = sf.SolutionID
and UG.SiteID = #SiteID
)

How does SQL Server Update rows with more than one value?

In an update statement for a temp table, how does SQL Server decide which value to use when there are multiple values returned, for example:
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
In this situation the problem is more than one dte_start_date is returned for each id value in the temp table. There is there's no index or unique value in the tables I'm working on so I need to know how SQL Server will choose between the different values.
It is non-deterministic. See the following example for a better understanding. Though it is not exactly the same scenario explained here, it is pretty similar
When the single value is to be retrieved from the database also use the SET statement with a query to set the value. For example:
SET #v_user_user_id = (SELECT u.user_id FROM users u WHERE u.login = #v_login);
Reason: Unlike Oracle, SQL Server does not raise an error if more than one row is returned from a SELECT query that is used to populate variables. The above query will throw an exception whereas the following will not throw an exception and the variable will contain a random value from the queried table(s).
SELECT #v_user_user_id = u.user_id FROM users u WHERE u.login = #v_login;
It is non-deterministic which value is used if you have a one two many relationship.
In MS-SQL-Sever (>=2005) i would use a CTE since it's a readable way to specify what i want using ROW_NUMBER. Another advantage of a CTE is that you can change it easily to do a select instead of an update(or delete) to see what will happen.
Assuming that you want the latest record(acc.to dte_start_date) for every id:
WITH CTE AS
(
SELECT a.*, rn = ROW_NUMBER() OVER (PARTITION BY a.id
ORDER BY a.dte_start_date DESC)
FROM #temp_table A
INNER JOIN table1 ON A.id = table1.id
)
UPDATE A
SET A.dte_start_date = table1.dte_start_date
FROM #temp_table A INNER JOIN CTE ON A.ID = CTE.ID
WHERE CTE.RN = 1

SQL - Conditional Left Join Count Performance is Slow

I am using SQL Server 2012.
I have three tables. Builders, Addresses and BuilderAddresses.
I have the following query which is used to give me my total count of records during paging:
SELECT COUNT(*) FROM Builders
LEFT JOIN Addresses ON Addresses.AddressId IN
(SELECT AddressId FROM BuilderAddresses WHERE BuilderId = Builders.BuilderId AND IsPrimary = 1)
WHERE Builders.[Email] LIKE '%TEST'%
ORDER BY Builders.[Name]
This query is particularly slow when records in the table approach 100k+. Does any one have any suggestions on how to get this query to execute faster??
On a table with 120K records, it take 452ms to get the count. When it comes to returning the records used in the paging, say 100 rows, it takes 11ms. I would really like to improve this if I can.
If I need to add greater detail, please let me know and I will edit the question.
The ORDER BY is not necessary for the COUNT, and you can remove that IN validation by joining with BuilderAdresses directly.
Try something like this:
SELECT COUNT(*)
FROM Builders b
LEFT JOIN BuilderAddresses ba ON ba.BuilderId = b.BuilderId AND isPrimary = 1
LEFT JOIN Addresses a ON a.AddressId = ba.AddressId
WHERE Builders.[Email] LIKE '%TEST' %
The problem is most likely to be with using IN as part of the join predicate. What it looks like you need to do is first join the junction table BuilderAddresses and then join Addresses, so something like this
SELECT COUNT(*) FROM Builders
JOIN BuilderAddresses ON BuilderAddresses.BuilderId = Builders.BuilderId AND isPrimary = 1
JOIN Addresses ON Addresses.AddressId = BuilderAddresses.AddressId
WHERE Builders.[Email] LIKE '%TEST%'
ORDER BY Builders.[Name]

Selecting data from 2 different databases and comparing them

Forgive me if this question has already been asked, but... I'm trying to select data from 2 different tables in a database and count all the data in one table that is equal to the data in the second table if that makes sense? Below is the code I am trying to use
$select = "SELECT * FROM client_id, clientid, COUNT(client_id) FROM enquiry, check_s WHERE client_id = clientid";
Your query appears to be syntactically wrong.
What you can try is to join the two tables on a primary key(id?) and any other fields you're trying to match. The basic syntax would be like this:
SELECT * FROM
DB1.Table1
JOIN DB2.Table2
ON DB1.Table1.PrimaryKey = DB2.Table2.PrimaryKey;
If you're looking for an exact data match, you may have to join the tables based on all fields(in the ON clause in the above query).
Edit:
Now that you've explained it, you can try this:
SELECT table1.*, count(*) as `n` FROM table1
JOIN table2
ON table1.field = table2.field;
Again, if you need to compare more fields, just include them in the ON clause, and set conditions in the WHERE clause.
I think you might be looking for something like this:
Lets say your main table name is Client and your secondary table (from the form) is Enquiry and the column which you want to compare in client is called client_id and the same column in Enquiry is called clientid.
Then you have
Select Count(Client.*)
From Client, Enquiry
Where Client.client_id = Enquiry.clientid
Group by Client.client_id

problem with IN clause in SQL

We have observed that there seems to be a maximum number of ids/variables which one can pass in the IN clause of SQL as comma separated values. To avoid this we are storing all the ids in a table and doing a SELECT within the IN clause. This however means extra database operations to store and retrieve ids. Is there any other way to use IN without SELECT?
Regards,
Sameer
In SQL Server 2008 you can declare a table variable and pass it to your query from the client or between the procedures.
For a modest number of values I would not have thought an IN (SELECT ..) would be that expensive on any rdbms.
You could INNER JOIN you IDs table or just break down the INs:
WHERE X IN (123,456 ...)
OR X IN (789,987 ...)
...
Agree with Alex
Instead of
Select * From TableA Where ID IN (Select ID from IDTable)
Use
Select * From TableA
INNER JOIN IDTable ON TableA.ID = IDTable.ID
The join will automatically filter the IDs for you.
If you put it in atable why are you still using the in clause, why not just join to the table?