Reputation: 654
I have a table Users
,
╔════╦═══════╦══════╗ ║ Id ║ Name ║ Db ║ ╠════╬═══════╬══════╣ ║ 1 ║ Peter ║ DB1 ║ ║ 2 ║ John ║ DB16 ║ ║ 3 ║ Alex ║ DB23 ║ ╚════╩═══════╩══════╝
and many databases that have the same structure (Same tables, same procedures, ...), so every database have a table named Project
, and this is the structure of Project
table,
╔════╦═════════╦═════════════╗ ║ Id ║ Request ║ Information ║ ╠════╬═════════╬═════════════╣ ║ 1 ║ 126 ║ XB1 ║ ║ 2 ║ 126 ║ D6 ║ ║ 3 ║ 202 ║ BM-23 ║ ╚════╩═════════╩═════════════╝
So, when I query a database :
SELECT count(distinct([Request])) as nbrRequests
FROM [SRV02].[DB1].[dbo].[Project]
I get this result :
╔═════════════╗ ║ NbrRequests ║ ╠═════════════╣ ║ 2 ║ ╚═════════════╝
Now, what I want is to "link"/"join" ... results from the table Users
to this query, where the column Db
in Users
table is the name of my database, so I can get a result like this :
╔════╦═══════╦══════╦═════════════╗ ║ Id ║ Name ║ Db ║ NbrRequests ║ ╠════╬═══════╬══════╬═════════════╣ ║ 1 ║ Peter ║ DB1 ║ 2 ║ ║ 2 ║ John ║ DB16 ║ 3 ║ ║ 3 ║ Alex ║ DB23 ║ 6 ║ ╚════╩═══════╩══════╩═════════════╝
I'm trying with dynamic SQL, but no luck.
NB : Every user has only one database, and a database belong to only one user, it's one-to-one relationship
Upvotes: 5
Views: 217
Reputation: 654
Combining these 2 answers https://stackoverflow.com/a/35795690/1460399 and https://stackoverflow.com/a/35795189/1460399, I got this solution :
DECLARE @Query NVARCHAR(MAX)= 'SELECT u.Id, u.Name, u.Db, dbCts.nbrRequests FROM [Users] u INNER JOIN (';
DECLARE @QueryLength INT= LEN(@Query);
SELECT @Query = @Query
+CASE WHEN LEN(@Query) > @QueryLength THEN ' UNION ' ELSE '' END
+'SELECT '''+Db+''' as db, count(distinct(Request)) as nbrRequests FROM [SRV02].'+Db+'[Project]'
FROM Users;
SET @Query = @Query+') dbCts ON u.Db = dbCts.db';
EXECUTE (@Query);
Upvotes: 1
Reputation: 5040
Dynamic SQL can be very tricky.
This example builds the select query from the users table. The variable @Query is incremented for each line returned by the Users table. Each row returns a query that joins the local users table to the projects table in a remote db. The results of each query are UNIONED together.
Example
-- Wil holds our dynamic query.
DECLARE @Query NVARCHAR(MAX) = '';
-- Builds our dynamic statement.
SELECT
@Query =
@Query
+ CASE WHEN LEN(@Query) > 0 THEN ' UNION ALL ' ELSE '' END
+ 'SELECT u.Id, u.Name, u.Db, COUNT(DISTINCT p.Request) AS NbrRequest '
+ 'FROM [SVR02].' + QUOTENAME(DB) + 'dbo.Project AS p INNER JOIN Users u ON u.Db= p.Db '
+ 'GROUP BY u.Id, u.Name, u.Db'
FROM
Users
;
-- Executes the dynamic statement.
EXECUTE (@Query);
This example uses QUOTENAME to help avoid SQL injection attacks.
Upvotes: 1
Reputation: 23381
The way you can do it is with a UNION counting every specific database table and giving it a identification for the database, like this:
SELECT u.Id, u.Name, u.Db, dbCts.nbrRequests
FROM [Users] u INNER JOIN
(SELECT 'DB1' as db, count(distinct([Request])) as nbrRequests
FROM [SRV02].[DB1].[dbo].[Project]
UNION
SELECT 'DB16', count(distinct([Request])) as nbrRequests
FROM [SRV02].[DB16].[dbo].[Project]
UNION
SELECT 'DB23', count(distinct([Request])) as nbrRequests
FROM [SRV02].[DB23].[dbo].[Project]
) dbCts ON u.Db = dbCts.db
Don't forget to add the server and schema to the Users
table I didn't because there is no such info on your question.
Also in order to do this, your connected user must have privileges on all databases.
Upvotes: 3