Query WSUS Database For Required Updates Per Server - sql-server

I searched the internet far and wide looking for a way to query the WSUS database to view the number of updates that need to be installed on a server. I found a partial answer on the following blog, but this answer will assume if the update is pending approval it is still required by a server (WSUS assumes this in their UI as well).
http://theboywonder.co.uk/2010/11/04/sql-query-for-wsus-3-needed-updates/

I hope this solution is useful for others.
SELECT left(tbComputerTarget.FullDomainName,30) as [Machine Name]
,count(tbComputerTarget.FullDomainName) as [# of Missing patches]
,tbComputerTarget.LastSyncTime as [Last Sync Time]
FROM tbUpdateStatusPerComputer INNER JOIN tbComputerTarget ON tbUpdateStatusPerComputer.TargetID =
tbComputerTarget.TargetID
WHERE (NOT (tbUpdateStatusPerComputer.SummarizationState IN (’1′, ’4′))) AND
tbUpdateStatusPerComputer.LocalUpdateID IN (SELECT LocalUpdateID FROM dbo.tbUpdate WHERE UpdateID IN
(SELECT UpdateID FROM PUBLIC_VIEWS.vUpdateApproval WHERE Action=’Install’))
GROUP BY tbComputerTarget.FullDomainName, tbComputerTarget.LastSyncTime
ORDER BY COUNT(*) DESC

i can filter for the update name
SELECT C.FULLDOMAINNAME AS COMPUTADOR,VU.DEFAULTTITLE AS ATUALIZAÇÃO,
'STATUS' = CASE
WHEN UP.SummarizationState = 1 THEN 'NÃO INSTALADO'
WHEN UP.SummarizationState = 2 THEN 'NÃO INSTALADO'
WHEN UP.SummarizationState = 3 THEN 'INSTALANDO'
WHEN UP.SummarizationState = 4 THEN 'INSTALADO'
WHEN UP.SummarizationState = 5 THEN 'FALHOU'
END
FROM TBCOMPUTERTARGET C
INNER JOIN tbUpdateStatusPerComputer UP ON C.TargetID = UP.TargetID
INNER JOIN tbUpdate U ON UP.LocalUpdateID = U.LocalUpdateID
INNER JOIN [PUBLIC_VIEWS].[vUpdate] VU ON U.UpdateID = VU.UpdateId
WHERE VU.DefaultTitle LIKE 'WINDOWS Internet Explorer 9 for Windows 7'
OR VU.DefaultTitle LIKE'Update for Microsoft Office 2010%'

Related

Custom SQL Query to HTML

I have been doing a lot of research and everything I find is using PHP and MySQL. I need to be able to access my ODBC SQL Server (my MRP system) and display a custom query on a webpage for a visual for my plant. I have not been able to find a way to establish a connection to the database nor the correct way to format the query to display data. Any and all recommendations and formatting corrections are greatly appreciated. I am not even sure HTML is the route I need to go. I just need to build a table based on this data with further ability to format using specific string values from the table.
The query is below:
with cte as
(
SELECT DISTINCT
orout.PartNo,
sched.JobNo,
sched.StepNo,
orout.DeptNum AS MachCell,
orout.WorkCntr as Descrip,
agg.sumHours as HrsLeft,
agg.sumManHrs,
agg.minStartDate,
agg.maxEndDate,
sched.Priority,
od.QtyToMake,
isnull(tt2.QtyComplete,0) as QtyComplete,
CASE
WHEN isnull(tt2.QtyComplete,0) = 0 THEN od.QtyToMake
ELSE (od.QtyToMake - tt2.QtyComplete)
END as QtyOpen,
orout.TotActHrs,
orout.TotEstHrs,
emp.EmplCode,
Emp.NewEmplShortName,
emp.WorkCntr,
wc.Descrip as wcDescrip,
CASE
WHEN emp.EmplCode IS NOT null THEN 1
ELSE 0
END AS LoginPriority
FROM Scheduling as sched
LEFT JOIN OrderRouting as orout
ON orout.JobNo = sched.JobNo AND orout.StepNo = sched.StepNo
LEFT JOIN OrderDet as od
ON orout.JobNo = od.JobNo
LEFT JOIN
(
SELECT
JobNo,
online.EmplCode,
EmplCode.NewEmplShortName,
WorkCntr,
StepNo
FROM Online
INNER JOIN EmplCode
ON EmplCode.EmplCode = online.EmplCode
) emp
ON emp.JobNo = orout.JobNo and emp.StepNo = orout.StepNo
LEFT JOIN
(
SELECT
JobNo,
StepNo,
SUM(ManHrs) as sumManHrs,
SUM(Hours) as sumHours,
MIN(StartDate) as minStartDate,
MAX(EndDate) as maxEndDate
FROM
Scheduling
GROUP BY JobNo, StepNo
) agg
ON agg.JobNo = sched.JobNo AND agg.StepNo = sched.StepNo
LEFT JOIN TimeTicketDet as tt
ON tt.JobNo = orout.JobNo and tt.StepNo = orout.StepNo
LEFT JOIN
(
SELECT
JobNo,
StepNo,
SUM(PiecesFinished+PiecesScrapped) as QtyComplete
FROM
TimeTicketDet as tt2
GROUP BY JobNo, StepNo
) tt2
ON tt2.JobNo = orout.JobNo and tt2.StepNo = tt.StepNo
LEFT JOIN WorkCntr as wc
ON emp.WorkCntr = wc.WorkCntr
WHERE
sched.Priority > 0
)
SELECT *
FROM CTE
WHERE
Descrip = 'MACHINE2'
ORDER BY
LoginPriority DESC, Priority DESC, minStartDate
I would suggest looking for an off-the-shelf application that can use a SQL view as a data source. You can then write a view in SQL to return the data you need displaying, then leave the application to handle everything in the UI.
I've not used any in-depth, and I'm not affiliated with any, but the two I've played with in the past are https://www.tableau.com/ and https://powerbi.microsoft.com. Tableau more of a dashboard tool (and maybe a bit pricey), but I think PowerBI is free, but they're just examples of something you can use. Have a look around, but you should be able to find something that you can use.

Visual Studio database schema compare is very slow

We've been using Visual Studio 2017's SQL Server Schema Comparison for all our (SQL Server 2016) migrations and deployments.
However, recently, it has become very slow, taking hours to process. If we uncheck the "Tables" object, it goes quickly. But when tables are checked, it is stuck on "Initializing comparison..." for ages.
I've not been able to find anything online that has helped us. Any ideas?
Initializing comparison...
What seemed to work for us is that if you excluded tables (in Schema Compare Options --> Object types --> Application-scoped -- > Tables), it runs quickly.
After its runs initially, you can compare again with tables selected, and its fine.
With the exception of this, the Visual Studio database Schema Compare is an awesome tool.
You can use MSSQL Server Management Studio's own comparison or use one of these tools:
https://www.agile-code.com/blog/choose-your-sql-server-schema-comparison-tool/
I had very similar problem and I was able to find a solution.
Query starting with SELECT * FROM (SELECT SCHEMA_NAME([o].[schema_id]) AS [SchemaName], from [sys].[spatial_indexes] and other tables had suboptimal plan and was running for hours, causing VS to timeout and retry.
Plan guide included below solved the problem for me.
Because VS sends all queries in one batch during 1st attempt to get results plan guide will not kick in. After query times out, VS will retry this query in its own batch and plan guide will be applied.
To speed up the process even more and don't wait for time out you can kill VS session when it is stuck on this query and force retry.
EXEC sp_create_plan_guide
#name = N'VS Schema Comp Spatial Idxs',
#stmt = N'SELECT * FROM (
SELECT
SCHEMA_NAME([o].[schema_id]) AS [SchemaName],
[si].[object_id] AS [ColumnSourceId],
[o].[name] AS [ColumnSourceName],
[o].[type] AS [ColumnSourceType],
[ic].[column_id] AS [ColumnId],
[c].[name] AS [ColumnName],
[si].[index_id] AS [IndexId],
[si].[name] AS [IndexName],
[ds].[type] AS [DataspaceType],
[ds].[data_space_id] AS [DataspaceId],
[ds].[name] AS [DataspaceName],
[si].[fill_factor] AS [FillFactor],
[si].[is_padded] AS [IsPadded],
[si].[is_disabled] AS [IsDisabled],
[si].[allow_page_locks] AS [DoAllowPageLocks],
[si].[allow_row_locks] AS [DoAllowRowLocks],
[sit].[cells_per_object] AS [CellsPerObject],
[sit].[bounding_box_xmin] AS [XMin],
[sit].[bounding_box_xmax] AS [XMax],
[sit].[bounding_box_ymin] AS [YMin],
[sit].[bounding_box_ymax] AS [YMax],
[sit].[level_1_grid] AS [Level1Grid],
[sit].[level_2_grid] AS [Level2Grid],
[sit].[level_3_grid] AS [Level3Grid],
[sit].[level_4_grid] AS [Level4Grid],
[sit].[tessellation_scheme] AS [TessellationScheme],
[s].[no_recompute] AS [NoRecomputeStatistics],
[p].[data_compression] AS [DataCompressionId],
CONVERT(bit, CASE WHEN [ti].[data_space_id] = [ds].[data_space_id] THEN 1 ELSE 0 END)
AS [EqualsParentDataSpace]
FROM
[sys].[spatial_indexes] AS [si] WITH (NOLOCK)
INNER JOIN [sys].[objects] AS [o] WITH (NOLOCK) ON [si].[object_id] = [o].[object_id]
INNER JOIN [sys].[spatial_index_tessellations] [sit] WITH (NOLOCK) ON [si].[object_id] = [sit].[object_id] AND [si].[index_id] = [sit].[index_id]
INNER JOIN [sys].[data_spaces] AS [ds] WITH (NOLOCK) ON [ds].[data_space_id] = [si].[data_space_id]
INNER JOIN [sys].[index_columns] AS [ic] WITH (NOLOCK) ON [si].[object_id] = [ic].[object_id] AND [si].[index_id] = [ic].[index_id]
INNER JOIN [sys].[columns] AS [c] WITH (NOLOCK) ON [si].[object_id] = [c].[object_id] AND [ic].[column_id] = [c].[column_id]
INNER JOIN [sys].[objects] AS [o2] WITH (NOLOCK) ON [o2].[parent_object_id] = [si].[object_id]
INNER JOIN [sys].[stats] AS [s] WITH (NOLOCK) ON [o2].[object_id] = [s].[object_id] AND [s].[name] = [si].[name]
INNER JOIN [sys].[partitions] AS [p] WITH (NOLOCK) ON [p].[object_id] = [o2].[object_id] AND [p].[partition_number] = 1
LEFT JOIN [sys].[indexes] AS [ti] WITH (NOLOCK) ON [o].[object_id] = [ti].[object_id]
LEFT JOIN [sys].[tables] AS [t] WITH (NOLOCK) ON [t].[object_id] = [si].[object_id]
WHERE [si].[is_hypothetical] = 0
AND [ti].[index_id] < 2
AND OBJECTPROPERTY([o].[object_id], N''IsSystemTable'') = 0
AND ([t].[is_filetable] = 0 OR [t].[is_filetable] IS NULL)
AND ([o].[is_ms_shipped] = 0 AND NOT EXISTS (SELECT *
FROM [sys].[extended_properties]
WHERE [major_id] = [o].[object_id]
AND [minor_id] = 0
AND [class] = 1
AND [name] = N''microsoft_database_tools_support''
))
) AS [_results];
',
#type = N'SQL',
#module_or_batch = NULL,
#params = NULL,
#hints = N'OPTION (FORCE ORDER)';

SQLITE Complex select statement. Help me speed it up

Some may or may not consider this a complex statement, but for me (since I've only been doing statement for about a month) this one is. The below statement returns me the exact results I am looking for, but my problem is that it take over 95 seconds to run on a iMac. I need this statement to run on an iPhone. Can anyone thing of a better (quicker) way to do this?
select categories.category
from categories join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and (select count(*)
from (select (
select categories.category
from categories left join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and listings.id = categories_listings.listing_id) as region
from listings left join chamber_specifics
on chamber_specifics.listing_id=listings.id
where region = categories.category
and listings.association_id=1
and listings.status = 1
and downtown='Y')) >0
group by categories.category;
Let me know if more info is needed.
Thanks!
I came up with a statement that gets me the same results as in my question, but much fast at about 0.062 seconds to complete. Below is my Statement: (Thanks Rudu for the direction!)
select (
select categories.category
from categories left join categories_listings
where categories_listings.category_id = categories.id
and categories.association_id = 1
and listings.id = categories_listings.listing_id) as region
from listings left join chamber_specifics
on chamber_specifics.listing_id=listings.id
where listings.association_id=1
and listings.status = 1
and downtown='Y'
group by region

SQL Server: Multiple table joins with a WHERE clause

I'm using SQL Server and I'm having a difficult time trying to get the results from a SELECT query that I want. I've tried joining in different orders and using subqueries but nothing quite works the way I want. Take this contrived example of software applications, with different version levels, that might be installed on peoples computers.
I need to perform a JOIN with a WHERE, but for some reason I can't get the results I want.
Maybe I'm looking at my data wrong, I'm not quite sure why I can't get this to work.
Application table
ID Name
1 Word
2 Excel
3 Powerpoint
Software Table (contains version information for different applications)
ID ApplicationID Version
1 1 2003
2 1 2007
3 2 2003
4 2 2007
5 3 2003
6 3 2007
Software_Computer junction table
ID SoftwareID ComputerID
1 1 1
2 4 1
3 2 2
4 5 2
Computer table
ID ComputerName
1 Name1
2 Name2
I want a query that I could run where I select a specific computer to display what software version and application is has, but I also want it to display what application it does not have(the version would be a NULL since it doesn't have that software on it)
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN Software_Computer
ON Computer.ID = Software_Computer.ComputerID
JOIN Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = 1
I want the following result set
ComputerName Name Version
Name1 Word 2003
Name1 Excel 2007
Name1 Powerpoint NULL
But I just get
Results
ComputerName Name Version
Name1 Word 2003
Name1 Excel 2007
I thought the RIGHT JOIN would include all the results in the application table, even if they aren't associated with the computer. What am I missing/doing wrong?
When using LEFT JOIN or RIGHT JOIN, it makes a difference whether you put the filter in the WHERE or into the JOIN.
See this answer to a similar question I wrote some time ago:
What is the difference in these two queries as getting two different result set?
In short:
if you put it into the WHERE clause (like you did, the results that aren't associated with that computer are completely filtered out
if you put it into the JOIN instead, the results that aren't associated with that computer appear in the query result, only with NULL values
--> this is what you want
The third row you expect (the one with Powerpoint) is filtered out by the Computer.ID = 1 condition (try running the query with the Computer.ID = 1 or Computer.ID is null it to see what happens).
However, dropping that condition would not make sense, because after all, we want the list for a given Computer.
The only solution I see is performing a UNION between your original query and a new query that retrieves the list of application that are not found on that Computer.
The query might look like this:
DECLARE #ComputerId int
SET #ComputerId = 1
-- your original query
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN dbo.Software_Computer
ON Computer.ID = Software_Computer.ComputerID
JOIN dbo.Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN dbo.Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = #ComputerId
UNION
-- query that retrieves the applications not installed on the given computer
SELECT Computer.ComputerName, Application.Name, NULL as Version
FROM Computer, Application
WHERE Application.ID not in
(
SELECT s.ApplicationId
FROM Software_Computer sc
LEFT JOIN Software s on s.ID = sc.SoftwareId
WHERE sc.ComputerId = #ComputerId
)
AND Computer.id = #ComputerId
try this
DECLARE #Application TABLE(Id INT PRIMARY KEY, NAME VARCHAR(20))
INSERT #Application ( Id, NAME )
VALUES ( 1,'Word' ), ( 2,'Excel' ), ( 3,'PowerPoint' )
DECLARE #software TABLE(Id INT PRIMARY KEY, ApplicationId INT, Version INT)
INSERT #software ( Id, ApplicationId, Version )
VALUES ( 1,1, 2003 ), ( 2,1,2007 ), ( 3,2, 2003 ), ( 4,2,2007 ),( 5,3, 2003 ), ( 6,3,2007 )
DECLARE #Computer TABLE(Id INT PRIMARY KEY, NAME VARCHAR(20))
INSERT #Computer ( Id, NAME )
VALUES ( 1,'Name1' ), ( 2,'Name2' )
DECLARE #Software_Computer TABLE(Id INT PRIMARY KEY, SoftwareId int, ComputerId int)
INSERT #Software_Computer ( Id, SoftwareId, ComputerId )
VALUES ( 1,1, 1 ), ( 2,4,1 ), ( 3,2, 2 ), ( 4,5,2 )
SELECT Computer.Name ComputerName, Application.Name ApplicationName, MAX(Software2.Version) Version
FROM #Application Application
JOIN #Software Software
ON Application.ID = Software.ApplicationID
CROSS JOIN #Computer Computer
LEFT JOIN #Software_Computer Software_Computer
ON Software_Computer.ComputerId = Computer.Id AND Software_Computer.SoftwareId = Software.Id
LEFT JOIN #Software Software2
ON Software2.ID = Software_Computer.SoftwareID
WHERE Computer.ID = 1
GROUP BY Computer.Name, Application.Name
You need to do a LEFT JOIN.
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN dbo.Software_Computer
ON Computer.ID = Software_Computer.ComputerID
LEFT JOIN dbo.Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN dbo.Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = 1
Here is the explanation:
The result of a left outer join (or simply left join) for table A and
B always contains all records of the "left" table (A), even if the
join-condition does not find any matching record in the "right" table
(B). This means that if the ON clause matches 0 (zero) records in B,
the join will still return a row in the result—but with NULL in each
column from B. This means that a left outer join returns all the
values from the left table, plus matched values from the right table
(or NULL in case of no matching join predicate). If the right table
returns one row and the left table returns more than one matching row
for it, the values in the right table will be repeated for each
distinct row on the left table. From Oracle 9i onwards the LEFT OUTER
JOIN statement can be used as well as (+).
SELECT p.Name, v.Name
FROM Production.Product p
JOIN Purchasing.ProductVendor pv
ON p.ProductID = pv.ProductID
JOIN Purchasing.Vendor v
ON pv.BusinessEntityID = v.BusinessEntityID
WHERE ProductSubcategoryID = 15
ORDER BY v.Name;
You almost have it. You need a Right join to the application, So it knows that the right table which is application is important
SELECT Computer.ComputerName, Application.Name, Software.Version
FROM Computer
JOIN Software_Computer
ON Computer.ID = Software_Computer.ComputerID
Right JOIN Software
ON Software_Computer.SoftwareID = Software.ID
RIGHT JOIN Application
ON Application.ID = Software.ApplicationID
WHERE Computer.ID = 1
Try this working fine....
SELECT computer.NAME, application.NAME,software.Version FROM computer LEFT JOIN software_computer ON(computer.ID = software_computer.ComputerID)
LEFT JOIN software ON(software_computer.SoftwareID = Software.ID) LEFT JOIN application ON(application.ID = software.ApplicationID)
where computer.id = 1 group by application.NAME UNION SELECT computer.NAME, application.NAME,
NULL as Version FROM computer, application WHERE application.ID not in ( SELECT s.applicationId FROM software_computer sc LEFT JOIN software s
on s.ID = sc.SoftwareId WHERE sc.ComputerId = 1 )
AND computer.id = 1
select C.ComputerName, S.Version, A.Name
from Computer C inner join Software_Computer SC
on C.Id = SC.ComputerId
Inner join Software S
on SC.SoftwareID = S.Id
Inner join Application A
on S.ApplicationId = A.Id ;
SELECT Computer.Computer_Name, Application1.Name, Max(Soft.[Version]) as Version1
FROM Application1
inner JOIN Software
ON Application1.ID = Software.Application_Id
cross join Computer
Left JOIN Software_Computer
ON Software_Computer.Computer_Id = Computer.ID and Software_Computer.Software_Id = Software.Id
Left JOIN Software as Soft
ON Soft.Id = Software_Computer.Software_Id
WHERE Computer.ID = 1
GROUP BY Computer.Computer_Name, Application1.Name

Optimising this query. Relevant for DBA's working on a social network/community type website

I suppose this is quite a common SP present in socialnetworks and community type websites.
I have this SP that returns all of a user's friends on their 'friends' page order by those currently online, then alphabetically. It's taking quite a while to load and I am looking to speed it up.
I remember reading somewhere on SO that breaking up multiple joins into smaller result sets might speed it up. I haven't tried this yet but I am curious to see what other recommendations SO might have on this procedure.
DECLARE #userID INT -- This variable is parsed in
DECLARE #lastActivityMinutes INT
SET #lastActivitytMinutes = '15'
SELECT
Active = CASE WHEN DATEDIFF("n", b.LastActivityDate ,GETDATE()) < #lastActivityMinutes THEN 1 ELSE 0 END,
a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
FROM
Profile AS a
INNER JOIN aspnet_Users as b on b.userId = a.UserId
LEFT JOIN Friend AS x ON x.UserID = a.UserID
LEFT JOIN Friend AS z ON z.FriendID = a.UserID
WHERE ((x.FriendId = #userID AND x.status = 1) -- Status = 1 means friendship accepted
OR (z.UserID = #userID AND z.Status = 1))
GROUP BY a.userID, a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
ORDER BY Active DESC, DisplayName ASC
I am not sure how to clip in my execution plan but the main bottle neck seems to be occurring on a MERGE JOIN (Right Outer Join) that's costing me 29%. At various stages, Parallelism is also costing 9%, 6%, 5% and 9% for a total of 29% as well.
My initial thoughts are to first return the JOINED results from the Profile and aspnet tables with a CTE and then do LEFT JOINS to the Friends table.
You are joining Friend twice, using a LEFT JOIN, then you are removing the NULL's returned by the LEFT JOIN by WHERE condition, then using GROUP BY to get rid on distincts.
This is not the best query possible.
Why don't you just use this:
SELECT Active = CASE WHEN DATEDIFF("n", b.LastActivityDate ,GETDATE()) < #lastActivityMinutes THEN 1 ELSE 0 END,
a.DisplayName, a.ImageFile, a.UserId, b.LastActivityDate
FROM (
SELECT FriendID
FROM Friends
WHERE UserID = #UserId
AND status = 1
UNION
SELECT UserID
FROM Friends
WHERE FriendID = #UserId
AND status = 1
) x
INNER JOIN
Profile AS a
ON a.UserID = x.FriendID
INNER JOIN
aspnet_Users as b
ON b.userId = a.UserId
ORDER BY
Active DESC, DisplayName ASC

Resources