Collate data from different Databases into same output window - sql-server

I need to display data in different columns in the same output window from multiple different database sources. It would be ok to output this data to a file if necessary. For example say I have the following script that I need run on databases with identical schema:
SELECT TOP 3 item_id, COUNT(*) as itemcount_db1
FROM DB1.dbo.table
GROUP BY item_id ORDER BY itemcount_db1
SELECT TOP 3 item_id, COUNT(*) as itemcount_bd2
FROM DB2.dbo.table
GROUP BY item_id ORDER BY itemcount_bd2
So that the output would not be in two sequential and separate windows (as I hundreds of DBs and want to do a single copy and paste). I'm happy to create all of the individual scripts to get the data, just need to combine them somehow.

For one, you can use sp_MSforeachdb or a potential better one by Aaron Bertrand so you don't have to copy and paste all the scripts. I'm not sure you'd want the results going horizontally here, but instead just create a column with the DB flag. Here is a way using UNION and a CTE (since you need the order by for TOP).
with db1 as(
SELECT TOP 3
item_id,
COUNT(*) as itemcount
,'DB1'
FROM
DB1.dbo.table
GROUP BY
item_id
ORDER BY
itemcount_bd2)
db2 as(
SELECT TOP 3
item_id,
COUNT(*) as itemcount
,'DB2'
FROM
DB2.dbo.table
GROUP BY
item_id
ORDER BY
itemcount_bd2)
select * from db1
union all
select * from db2

Related

SQL Server - More efficient way of joining three tables without parent table

This is an issue I have been working on for a while, I have three tables, all of which share 3 of the same columns but there are rows that are unique to each row. I would like to combine all of the tables without duplicating rows. I have a working solution but I feel like it might not be the most efficient. I tried using joins but found that without a parent table, I wasn't getting the expected number of results. My solution which does yield the correct number of results(I've cut some columns for simplicity):
--Create table
CREATE TABLE #Temp
(
ID,
Date
)
-- Insert rows that are only in db1
INSERT INTO #Temp
SELECT
ID,
Date
FROM test.dbo.db1
-- Do not include rows shared by db1 and db2
EXCEPT
(
SELECT
ID,
Date
FROM test.dbo.db2
INTERSECT
SELECT
ID,
Date
FROM test.dbo.db1
)
EXCEPT
-- And not in db1 and db3
(
SELECT
ID,
Date
FROM test.dbo.db1
INTERSECT
SELECT
ID,
Date
FROM test.dbo.db3
)
EXCEPT
-- And not in db1, db2 and db3
** Code where I intersect all 3 tables
I repeat the above steps for all three tables and then add the intersections for each combined ID/Date(db1+d2+db3, db1+db2, etc...)
Does anyone know of a way to do this that is more direct and to the point? I have tried doing a full join of all of them but without a parent table with all of the ID's, I found the ID's that only appear in the other two tables don't show up.
SELECT
ID,
Date
FROM test.dbo.db1
UNION
SELECT
ID,
Date
FROM test.dbo.db2
UNION
SELECT
ID,
Date
FROM test.dbo.db3
The UNION takes care of removing duplicates.

SQL Server random rows on where clause

I need to select 10 random rows from a table, but it has to be done in the where clause, because the query is executed using another aplication that only allows to modify this part.
I searched for a lot of solutions (select top 10, RAND(), ORDER BY NEWID(), ...), but none work in the where clause.
There an option to do that? or some kind of workaround?
Try this:
SELECT *
FROM Test
WHERE Id IN (SELECT TOP 10 Id FROM Test ORDER BY NewId())
If your table has a unique column you can do something like :
SELECT * FROM TABLE WHERE PRIMARYCOLUMN IN (SELECT TOP(10) PRIMARYCOLUMN FROM TABLE ORDER BY NEWID())

Generate an sql query from multiple tables, then create new table

I have a tricky bit of sql query I need to write. To best explain it, I will post some pictures to show three tables. The first two are tables which already contain data, the last table will be the table I need created using data from the first two:
You can use JOIN for each column you want to get in final table:
SELECT
Width.itemNumber,
Width.itemValue as 'Width',
Height.itemValue as 'Height',
[Type].valueID as 'Type',
Frame.valueID as 'Frame',
Position.valueID as 'Position'
INTO third_table_name
FROM itemMaster_itemValue Width
JOIN itemMaster_itemValue Height ON Width.itemNumber=Height.itemNumber AND Height.itemPropertyID='Height'
JOIN itemMaster_EnumValue 'Type' ON Width.itemNumber=[Type].itemNumber AND [Type].itemPropertyID='Type'
JOIN itemMaster_EnumValue Frame ON Width.itemNumber=Frame.itemNumber AND Frame.itemPropertyID='Frame'
JOIN itemMaster_EnumValue Position ON Width.itemNumber=Position.itemNumber AND Position.itemPropertyID='Position'
WHERE Width.itemPropertyID='Width'
I'm not sure if you actually are wanting to create a table for the third view or just a query (in access) / view (in MS SQL Server). Here is how I would do it:
In MS-Access:
Step 1 (Which can end here if all you need is a way to see the data in this format)
TRANSFORM Max(P.vid) AS MaxOfvid
SELECT P.inum
FROM (SELECT itemNumber as inum, itemPropertyID as ival, itemValue as vid
FROM itemMaster_itemValue
UNION
SELECT Enum.itemNumber AS inum, Enum.itemPropertyID AS ival, Enum.valueID AS vid
FROM itemMaster_EnumValue AS Enum) AS P
GROUP BY P.inum
PIVOT P.ival;
Step 2 (If you need to actually create an additional table)
Select * INTO tableName FROM previousPivotQueryName;
That will get you what you need in Access.
The SQL Server part is a little different and can all be done in one T-SQL Statement dbo.test is the name of the table you will create... If you are creating a table for performance reasons then this statement can be put into a job and run nightly to create the table. The Drop Table line will have to be removed before the first time you run it or it will fail because the table will not exist yet:
Drop Table dbo.Test
Select * INTO dbo.Test FROM (
/*just use the following part if you only need a view*/
SELECT *
FROM (SELECT itemNumber as inum, itemPropertyID as ival, itemValue as vid
FROM dbo.itemMaster_itemValue
UNION
SELECT Enum.itemNumber AS inum, Enum.itemPropertyID AS ival, Enum.valueID AS vid
FROM dbo.itemMaster_EnumValue AS Enum) P
PIVOT (max(vid) FOR ival IN([Width],[Height],[Type],[Frame],[Position])) PV)PVT;
And that should get you what you need in the most efficient way possible without using a bunch of joins. :)

Summarizing count of multiple talbes in one row or column

I've designed a migration script and as the last sequence, I'm running the following two lines.
select count(*) from Origin
select count(*) from Destination
However, I'd like to present those numbers as cells in the same table. I haven't decided yet if it's most suitable to put them as separate rows in one column or adjacent columns on one row but I do want them in the same table.
How can I select stuff from those selects into vertical/horizontal line-up?
I've tried select on them both with and without parentheses but id didn't work out (probably because of the missing from)...
This questions is related to another one but differs in two aspects. Firstly, it's much more to-the-point and clearer states the issue. Secondly, it asks about both horizontal and vertical line-up of the selected values whereas the linked questions only regards the former.
select
select count(*) from Origin,
select count(*) from Destination
select(
select count(*) from Origin,
select count(*) from Destination)
You need to nest the two select statements under a main (top) SELECT in order to get one row with the counts of both tables:
SELECT
(select count(*) from Origin) AS OriginCount,
(select count(*) from Destination) AS DestinationCount
SQLFiddle for the above query
I hope this is what you are looking for, since the "same table" you are mentioning is slightly confusing. (I'm assuming you're referring to result set)
Alternatively you can use UNION ALL to return two cells with the count of both tables.
SELECT COUNT(*), 'Origin' 'Table' FROM ORIGIN
UNION ALL
SELECT COUNT(*), 'Destination' 'Table' FROM Destination
SQLFiddle with UNION ALL
SQLFiddle with UNION
I recommend adding the second text column so that you know the corresponding table for each number.
As opposed to simple UNION the UNION ALL command will return two rows everytime. The UNION command will generate a single result (single cell) if the count of rows in both tables is the same (the same number).
...or if you want vertical...
select 'OriginalCount' as Type, count(*)
from origin
union
select 'DestinationCount' as Type, count(*)
from destination

Use SQL Server CTE to retrieve multiple result sets

I was wondering how I can retrieve multiple result sets based on one CTE? Something like what I have below - but obviously this doesn't work.
Does anyone know how I can get these 2 (or more) sets of data, based on that one CTE? (more, as in that it would be nice to get the total record count from this same CTE as well.)
;WITH CTE AS
(
SELECT
Column1, Column2, Column3
FROM
Product
WHERE
Name LIKE '%Hat%' AND Description Like '%MyBrand%'
)
SELECT DISTINCT CategoryId FROM CTE
SELECT DISTINCT BrandId FROM CTE
A CTE only exists for the query immediately following it, so it's not possible to use it for two separate select statements. You'll either need to persist the data in something like a temp table, or construct/invoke the CTE twice.

Resources