I’m going to point people to this that have “My Group By isn’t working” questions…
The Joys of SQL:
Did you know that the SQL language allows you to do amazing analysis of data such as aggregate functions?
SELECT t.session_id,
t.request_id,
SUM(t.user_objects_alloc_page_count) AS UserObjectAllocated,
SUM(t.user_objects_dealloc_page_count) AS UserObjectDeallocated
FROM sys.dm_db_task_space_usage AS t
GROUP BY t.session_id,
t.request_id;
0’s! Amazing!
The Pains of SQL:
But…if you forget to put in the GROUP BY clause, as a ski instructor once said, you’re going to have a bad time!
Pizza…French Fries…Pizza
The Repetitiveness of Questioners:
So some eager yet lost scholar ventures into this land of aggregate functions, reads the error message and adds in a GROUP BY clause.
SELECT t.session_id,
t.request_id,
SUM(t.user_objects_alloc_page_count) AS UserObjectAllocated,
SUM(t.user_objects_dealloc_page_count) AS UserObjectDeallocated
FROM sys.dm_db_task_space_usage AS t
GROUP BY t.session_id;
Trawling the bulletin boards, question sites, and forums – okay maybe a quick question online, it’s called poetic exaggerationpeople! – they eventually learn the folly of their ways and correct their mistake.
SELECT t.session_id,
t.request_id,
SUM(t.user_objects_alloc_page_count) AS UserObjectAllocated,
SUM(t.user_objects_dealloc_page_count) AS UserObjectDeallocated
FROM sys.dm_db_task_space_usage AS t
GROUP BY t.session_id,
t.request_id;
PIZZA!
The Euphoria of SQL Prompt:
Now I consider myself lucky that work has invested in the RedGate tools, and right now, especially SQL Prompt.
I’m not going to talk about “Save and Recover Lost Tabs” – saved my ass many times.
I’m not going to talk about “Code Formatting” – saved my sanity many times.
I’m going to talk about “Autocomplete”.
A well-known secret with SQL Prompt’s autocomplete is the snippets feature. With this, you can increase your productivity by 75% from typing out G R O U P [space] B Y and instead use gb and hit tab.
Wait? I can order Pizza?
The Ecstasy of SQL Prompt:
Do not get me wrong, a 75% increase in productivity? I’ll take that!
That is a well-known secret though, and it’s slightly hard to get excited about a well-known secret.
However, what if I told you that SQL Prompt had another lesser-known secret that can increase your productivity and ensure that you do not forgot to add the necessary columns to your GROUP BY clause?
Interested? Ah c’mon!
You sure you’re not interested?…. That’s better!
So first of all, let us increase the number of non-aggregated columns in our SELECT to include database_id, is_remote_work, and exec_context_id. Including our session_id and request_id these are all columns that we are going to need to add to our GROUP BY clause, because…well…business logic.
Only problem is ain’t nobody got time for that.
SQL Prompt knows this and adds the following little snippet after a GROUP BY autocomplete.
Whoa! Whoa! You can deliver Pizza to me?
Hitting tab on that includes everything in the SELECT that is not part of an aggregate function, leaving us to concern ourselves with loftier things…
Like whatever happened to Pizza in 30 mins or free?
Pizza:
Now I don’t work for pizza RedGate, I’m not affiliated with them, and I don’t get any money off of them. In fact, I’d say that they’d happily pay me not to write about them but when I found this autocomplete feature, I got too happy not to share it!
So save yourself the trouble of typing everything out and spare yourself the pain of error messages.
Use this lesser-known secret and have more time for pizza.
However, do me a favour and in your favourite search engine, do a search for “stackoverflow sql server wide tables” (Google search included for your benefit).
For some reason, people have a slight fascination with wwwwwiiiiiiiiddddeeeee tables!
So thanks to the excellent work done by Jana, you have now identified the tables with similar structure, but what about if we want to know which column names match exactly?
I recently had this problem with consolidating copies of tables of medium to wide length in a database and needed to know. So I created a little snippet of code to help me out and I present it to you, in all of it’s unashamed vulnerability, in the hope that it can help you out.
Be warned: Thar be PIVOTs ahead!
Ahoy, matey!
So we’ve got two tables that are slightly different, not completely different (hey, they could be) but different enough to be similar without matching… (differently similar?)
Our task is to find out which columns are in both tables, which columns are only in 1 table, and which columns are only in the other.
Now this isn’t so bad manually, especially if you only need to do this once, maybe twice. What happens though if you need to do it with multiple pairs of tables? Or multiple pairs of wide tables like our search engines showed us above?
So let us do what all DBAs should do when they have a repetitive, manual task stopping them from doing more fun important things: Automate it away!
Avast Ye!
Our two tables are as follows:
CREATE TABLE dbo.DifferenceTable01
(
col1 int,
col2 int,
col4 int,
col6 int
);
GO
CREATE TABLE dbo.DifferenceTable02
(
col2 int,
col3 int,
col4 int,
col5 int
);
GO
Now we can use the sys.columns table to check out the different columns in the table but the results are, well, meh
SELECT
OBJECT_NAME([object_id]) AS TableName,
[name] AS ColumnName
FROM sys.columns
WHERE [object_id] IN
(
OBJECT_ID(N'dbo.DifferenceTable01', N'U'),
OBJECT_ID(N'dbo.DifferenceTable02', N'U')
);
GO
Even if I ordered it, it would still be “meh”…
That is not really going to work out for us…
So I’m not liking the look of this, and going through the results, it seems to me that these results are just not useful. This isn’t the computers fault – it’s done exactly what I’ve told it to do – but a more useful result would be a list of columns and then either a simple ‘Yes’, or a ‘No’.
As anyone who has seen me dance can attest to, I can neither shake, rattle, nor roll. And I definitely do not normally PIVOT. However, as I’m trying to know my tools, I do know that this is the syntax that I need.
PIVOT rotates a table-valued expression by turning the unique values from one column in the expression into multiple columns in the output, and performs aggregations where they are required on any remaining column values that are wanted in the final output.
So after looking up the syntax for this once (ok, 5 times!) I managed to come out with a script that I’m reasonably happy with.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters. Learn more about bidirectional Unicode characters
So much better! This way, no matter how long the tables, I can easily figure out what columns are in what table(s) based on their names.
Shiver Me Timbers!
Isn’t it always the way after you’ve done something, you realise a much easier way to do it?
The Old Seadog!
I’ve talked about automation in this post and I have yet to mention PowerShell. I bow my head in shame.
Especially when it has a native command like Compare-Object.
help Compare-Object -ShowWindow
Synopsis
Compares two sets of objects.
Description
The Compare-Object cmdlet compares two sets of objects. One set of objects is the “reference set,” and the other set is the “difference set.”
The result of the comparison indicates whether a property value appeared only in the object from the reference set (indicated by the <= symbol), only in the object from the difference set (indicated by the => symbol) or, if the IncludeEqual parameter is specified, in both objects (indicated by the == symbol).
If the reference set or the difference set is null ($null), this cmdlet generates a terminating error.
So the question we have to ask ourselves now is “Can we do what we did with the PIVOTs easier?”
The Old Salt.
I’ve recently found out about splatting so, of course, I’ve started to use it EVERYWHERE!
Let’s “splat” our two parameters
$Table01Param = @{
ServerInstance = 'localhost\SQLDEV2K14'
Database = 'master'
Query = "SELECT OBJECT_NAME([object_id]) AS TableName, [name] AS ColumnName FROM sys.columns WHERE [object_id] = OBJECT_ID(N'dbo.DifferenceTable01', N'U');"
}
$Table02Param = @{
ServerInstance = 'localhost\SQLDEV2K14'
Database = 'master'
Query = "SELECT OBJECT_NAME([object_id]) AS TableName, [name] AS ColumnName FROM sys.columns WHERE [object_id] = OBJECT_ID(N'dbo.DifferenceTable02', N'U');"
}
And we now save ourselves the trouble of writing the parameters to the functions.
And for anyone saying “Yeah, but who knows what ‘SideIndicator’ means!”, I advise you to read the help with PowerShell. It helps a-lot!
The result of the comparison indicates whether a property value appeared only in the object from the reference set (indicated by the <= symbol), only in the object from the difference set (indicated by the => symbol) or, if the IncludeEqual parameter is specified, in both objects (indicated by the == symbol).
If you are still complaining about it – “You can’t have the HumanReadableFormat column like you did in T-SQL” – then please stop. There are experts out there who can make you go “wow” with what they do. I’m still learning but even I have an answer to that.
I’m not trying to argue with who would win between T-SQL and PowerShell, that was definitely not my intention with this post. T-SQL is my first language love, PowerShell is very quickly becoming my second (and that’s not just because it’s the only other langauge I know).
They both accompolish the same thing!
It’s just a matter of preference, that’s all, not a matter of competition. You want to work in SSMS, PIVOT it up! You like PowerShell, hammer that Compare-Object nail!
Whatever works for you.
My first idea for this was T-SQL but it turns out for me that PowerShell is the easier option. Don’t rule out one, just because the other was the first thing to pop into your head.
Now I’m going to go before I make a joke about Pirates, SQL and the R language…
A while back I was testing attempting to access SQL Server using a defined port number.
To do that, you have to access SQL Server Configuration Manager to specify the port number, or at least I think you do (If you don’t have to do it this way, please, oh please, let me know!).
So, since my laptop is running on Windows10, I open up the Start menu, type in “config” and…nothing! No SQL Server Configuration Manager! The closest I got was the configuration manager for Reporting Server.
I’m shocked by this especially because when I type it into the Start menu now, I get…
Well it turns out that, for me, the default path is now in…
C:\Windows\sysWOW64\SQLServerManager”<nn>”.msc
I say “<nn>” because it’s a number dependant on what version of SQL Server that you are running.
For example, I have a 2012, a 2014 and a 2016 version on my laptop so I have 3 versions of SQL Server Configuration Manager.
I may have been msc-taken, get it? 🙂
Seriously, is that it?
Nope, that ain’t it.
Opening up Windows Explorer, going all the way down to that level just to get the config manager? Ain’t nobody got time for that!
They say “imitation is the greatest form of flattery” so taking ideas garnered from dbatools and the fact that I’m just finished a pre-con for SQL Saturday Boston in PowerShell from Mike Fal ( b | t ), thank you Andy Mallon ( b | t ) for pushing me out of my comfort zone even if it was only to just sign up!, I’ve created a little PowerShell script to let me choose and open a SQL Server Configuration Manager.