I’ve built a few tables and queries in SQL Server, but now I’m stuck as to how to make them work together in this latest task.
There’s a table, we’ll called it ServerAssessment. It has an inventory of servers, such as their Name and their Server Edition, which is Developer, Production, Unknown, etc. There’s much larger table called DatabaseDetails that contains thousands of records regarding IDs. Each row has a Server Name, a User Name, and other details not needed here.
The difficulty I’m having is that I need to produce a query that lists only Developer servers (WHERE Server Edition = 'Developer') but also then follows up and lists every distinct User Name (from DatabaseDetails) following it.
From a SQL logic standpoint, I am not sure how this is best completed. It would look something like this, I would think? Or am I coming at this completely from the wrong angle?
ServerA001 User00001 User00002 User00003 User00111
ServerA015 User00001 User00002 User60005 User29031 User11111
ServerC037 User00001 User00009
ServerD066 User00001 User00002 User00003 User12312 User12333, User14141
ServerN123 User00001 User00003 User00009
Again, a user may have access to many, many servers. Should instead of listing everything out by distinct server, instead transpose everything so it's by distinct/unique User, and then list out the servers? Would one be more ideal in a professional atmosphere?
All I have currently is something short and sweet, to join the tables and make sure only Developer is returned.
SELECT
DISTINCT [Server Name]
, [Server Edition]
FROM [ServerAssessment] AS tabDI
FULL JOIN [DatabaseDetails] AS tabUD
ON tabDI.[Server Name] = tabUD.[Server Name]
WHERE [SQL Server Edition] = 'Developer'
ORDER BY [Computer Name] ASC
PS: These were originally tables in Excel, but I imported this into SQL Server since I feel more comfortable with SQL as of my work the last few months.
First, using a full join will give you records from details that are not directly related to developer servers. You want to use a left join instead to get all development servers but only details related to them.
Second you will have to look up how to do a dynamic sql pivot if you want to do this in SQL. This will cause trouble when creating a report as the number of columns will change. I suggest you use a reporting tool that can auto-pivot for you. I did something similar using SSRS/
I would use ROW_NUMBER function togheter with PIVOT operator thus:
SELECT *
FROM (
SELECT /*DISTINCT*/ tabDI.[ServerName], [UserName],
ColNum = ROW_NUMBER() OVER(PARTITION BY tabDI.[ServerName] ORDER BY [UserName])
FROM (VALUES
('ServerA001', 'Developer'),
('ServerA002', 'Enterprise'),
('ServerA015', 'Developer')
) AS tabDI ([ServerName], [SQL Server Edition]) -- [ServerAssessment]
LEFT JOIN (VALUES -- LEFT JOIN for servers without users
('ServerA001', 'User00001'),
('ServerA001', 'User00002'),
('ServerA001', 'User00003'),
('ServerA001', 'User00006'),
('ServerA002', 'User00001'),
('ServerA015', 'User00003'),
('ServerA015', 'User00004')
) AS tabUD ([ServerName], [UserName]) -- [DatabaseDetails]
ON tabDI.[ServerName] = tabUD.[ServerName]
WHERE [SQL Server Edition] = 'Developer'
) x
PIVOT ( MAX(x.UserName) FOR x.ColNum IN ([1], [2], [3], [4] /*, ...*/) ) y
ORDER BY y.[ServerName]
Note: This solution works for a limited number of users (4 in above case).
Related
I am new to SQL and DB management. I am working on writing queries based on a schema which you can find below. This is an exercise for me to get familiar reading, writing queries on SQL Server for my job. Could you please help me out defining query based on the schema and simply explain the logic?
Thanks a lot!
SQL Server is my DBMS and here are the question
Display ID, First Name, Last Name, and Hits to display all players with more than 2000 career hits.
This one you can get by typing this query in Microsoft SQL Server
SELECT
MLB_PLAYERS.FIRST_NAME,
MLB_PLAYERS.LAST_NAME,
MLB_PLAYERS.ID,
CAREER_STATS.HITS
FROM
MLB_PLAYERS LEFT JOIN KEY_GAMES_STATS on MLB_PLAYERS.ID=CAREER_STATS.ID
WHERE
CAREER_STATS.HITS>2000
So you have a simple structure to follow:
SELECT
FROM
WHERE
GROUP BY
HAVING
ORDER BY
But you decide to get only 3 of them, which is select, from and where. By SELECT you decide which columns you wanna have as an output. Then in FROM you have to choose tables from which you wanna take your variables. But if you decide to use 2 different tables you need to join them. I used left join because I wanted to match hits to existing players. We can match them by similar key, in this case this is their ID. And eventually, you can use where to apply conditions to your queries
I guess you could do it with a join and a group
select p.MLB_PLAYERS.FIRST_NAME,
p.MLB_PLAYERS.LAST_NAME,
p.MLB_PLAYERS.ID,
count(g.KEY_GAMES_STATS.HITS) as hits
from MLB_PLAYERS p
left join KEY_GAMES_STATS on p.ID = g.ID -- not sure how to link there 2 tables
group by p.MLB_PLAYERS.FIRST_NAME,
p.MLB_PLAYERS.LAST_NAME,
p.MLB_PLAYERS.ID
having count(g.KEY_GAMES_STATS.HITS) > 2000
I'm writing (in .NET) a login screen that allows the login to connect to a SQL Server. Once they've put in the server name and their credentials, it should then show a list of databases for them to connect to, but, the databases need to be of the right structure. This will be identified within each database by the existence of a ref.Config table, and a row in that table with appropriate values. There may be a whole bunch of other databases on the server for other purposes. I don't know at designtime.
Ideally what I'd like to do is something like this:
SELECT m.name
FROM MASTER.sys.databases m
CROSS APPLY (SELECT *
FROM {m.name}.INFORMATION_SCHEMA.TABLES t
WHERE t.TABLE_SCHEMA = 'ref'
AND t.TABLE_NAME 'Config') dbs
CROSS APPLY (SELECT *
FROM {m.name}.ref.Config c
WHERE c.KeyName = 'DatabaseMagicNumber'
AND c.KeyValue = '12345678') config
WHERE HAS_DBACCESS(m.name) = 1
ORDER BY m.name
Where m.name gets substituted into the subqueries after evaluation (I know the above isn't valid SQL). Is there a way to do this, or do I have to run a query on each database? I am unable to have a stored procedure on the server at this point. Ideally I just want one SQL statement that will return the names of all databases that conform to the structure I expect.
I just registered and want to ask.
I learn sql queries not so long time and I got a trouble when I decided to move a table to another database. A few articles were read about building long subqueries , but they didn't help me.
Everything works perfect before that my action.
I just moved the table and tried to rewrite the query while whole day.
update [dbo].Full
set [salary] = 1000
where [dbo].Full.id in (
select distinct k1.id
from (
select id, Topic, User
from Full
where User not in (select distinct topic_name from [DB_1].dbo.S_School)
) k1
where k1.id not in (
select distinct k2.id
from (
select id, Topic, User
from Full
where User not in (select distinct topic_name from [DB_1].dbo.Shool)
) k2,
List_School t3
where charindex (t3.NameApp, k2.Topic)>5
)
)
I moved table List_School to database [DB_1] and I can't to bend with it.
I can't write [DB_1].dbo.List_School. Should I use one more subquery?
I even thought about create a few temporary tables but it can influence on speed of execution.
Sql gurus , please invest some your time on me. Thank you in advance.
I will be happy for each hint, which you give me.
There appear to be a number of issues. You are comparing the user column to the topic_name column. An expected meaning of those column names would suggest you are not comparing the correct columns. But that is a guess.
In the final subquery you have an ansi join on table List_School but no join columns which means the join witk k2 is a cartesian product (aka cross join) which is not what you would want in most situations. Again a guess as no details of actual problem data or error messages was provided.
I'm trying to Remove the Duplicate Header of my Query...
here's my query
Select po.BranchOrderNumber,pod.ItemCode, pod.ItemDescription From RetailPosOrders po
INNER JOIN RetailPosOrderDetails pod
ON po.BranchOrderID = pod.OrderID
my query's result now look's like this.
now what I want is something like this.
thanks in advance. I was planning to use this on Report builder.. I am using Microsoft Sql Server 2014.
This is the type of transformation that is best done at the application level. It is possible in SQL, but do recall that SQL queries and result sets -- by default -- are unordered. Your desired results have an ordering.
But, you can do this using row_number():
Select (case when row_number() over (partition by po.BranchOrderNumber order by pod.ItemCode) = 1
then po.BranchOrderNumber else ''
end) as BranchOrderNumber
pod.ItemCode, pod.ItemDescription
From RetailPosOrders po INNER JOIN
RetailPosOrderDetails pod
ON po.BranchOrderID = pod.OrderID
Order by po.BranchOrderNumber, pod.ItemCode;
This assumes that po.BranchOrderNumber -- despite its name -- is stored as a string (the leading zeroes suggest that this is the case).
Also, a couple of important things:
The outer order by needs to be the same as the fields used in the over clause.
The fields need to uniquely define each row in the result set. The order by in SQL is not stable, meaning that keys with the same value can appear in any order, even for different runs of the same query.
There is no way to do this in Mssql server itself.
I think you have to do it in the application level if you are going to display it using console/ win / web application.
I am getting the well-documented error:
ORDER BY items must appear in the select list if SELECT DISTINCT is specified.
Here's my SQL statement:
INSERT INTO PropertyList
(PropertyID, Initials)
SELECT DISTINCT P.PropertyID, "vSTEBCodes"
FROM Property AS P INNER JOIN ValiditySTEBCodes AS VC
ON P.ControlNumber=VC.ControlNumber
As you can see there is no ORDER BY statement in sight. Presumably there is an implied ORDER BY in there somewhere, but I can't see it.
I am running this statement against linked tables in MS Access that are linked to a SQL Server 2008 back-end. When I run it from a full version of Access 2002, it runs without issue. If I try to run it from an Access 2000 runtime I receive the error shown.
I know that Access has a tendency to re-write queries in the background before forwarding them to ODBC sources (especially multi-record INSERTs and UPDATEs). I'm thinking that may be the issue.
Compiling from the comments, try:
INSERT INTO dbo.PropertyList(PropertyID, Initials)
SELECT P.PropertyID, Initials = 'vSTEBCodes' -- alias and single quotes
FROM dbo.Property AS P -- always use schema prefix
INNER JOIN dbo.ValiditySTEBCodes AS VC
ON P.ControlNumber = VC.ControlNumber
GROUP BY P.PropertyID -- instead of DISTINCT
ORDER BY P.PropertyID; -- maybe overrides Access stupidity