SQL Server: Counting Inventory Issue (with subquery) - sql

I currently have a query that is going out into an inventory table (of servers), filtering which ones are 'Developer', and producing a list of distinct users from an audit-related table. Essentially, trying to find out who has access to development servers in this particular inventory.
Everything worked until I added the second line, which I commented out in the code below:
select distinct tAudit.[USER_ID]
--, count(tAudit.[USER_ID]) AS [USER_COUNT]
from table_audit as tAudit
where tAudit.inst_name IN (
SELECT (SUBSTRING([Computer Name],0,CHARINDEX('.',[Computer Name],0))) AS INST_NAME
FROM table_server_inventory
WHERE [SQL Server Edition] = 'Developer'
)
order by tAudit.user_id asc
So, the question is: How can I count how many times a particular user appears? Is there a conflict with the fact I am using distinct? There's another query I produced, purely to see if I was on the right track. This is an example:
select tAudit.[USER_ID]
, count(tAudit.[USER_ID]) AS [USER_COUNT]
from table_audit as tAudit
where tAudit.user_id IN ('user_001', 'user_009', 'user_199', 'user_222')
group by tAudit.user_id
And it looked something like this:
USER_ID USER_COUNT
user_001 5
user_009 32
user_199 14
user_222 8
Ideally, when the primary query is working it'll look like the example above, just with dozens more results.
NOTE: The table_audit is actually very large and lists servers and users each time. Example:
COMPUTER_NAME USER_ID
serverAA user_001
serverAA user_009
serverAA user_199
serverAA user_222
serverBB user_001
serverBB user_009
serverCC user_001
serverCC user_199
serverCC user_222

You just want a GROUP BY query, not SELECT DISTINCT:
select tAudit.[USER_ID], count(tAudit.[USER_ID]) AS [USER_COUNT]
from table_audit as tAudit
where tAudit.inst_name IN (
SELECT (SUBSTRING([Computer Name],0,CHARINDEX('.',[Computer Name],0))) AS INST_NAME
FROM table_server_inventory
WHERE [SQL Server Edition] = 'Developer'
)
group by tAudit.[USER_ID]
order by tAudit.user_id asc

Related

How to modify query to walk entire table rather than a single

I wrote several SQL queries and executed them against my table. Each individual query worked. I kept adding functionality until I got a really ugly working query. The problem is that I have to manually change a value every time I want to use it. Can you assist in making this query automatic rather than “manual”?
I am working with DB2.
Table below shows customers (cid) from 1 to 3. 'club' is a book seller, and 'qnty' is the number of books the customer bought from each 'club'. The full table has 45 customers.
Image below shows all the table elements for the first 3 users (cid=1 OR cid=2 OR cid=3). The final purpose of all my queries (once combined) is it to find the single 'club' with the largest 'qnty' for each 'cid'. So for 'cid =1' the 'club' is Readers Digest with 'qnty' of 3. For 'cid=2' the 'club' is YRB Gold with 'qnty' of 5. On and on until cid 45 is reached.
To give you a background on what I did here are my queries:
(Query 1-starting point for cid=1)
SELECT * FROM yrb_purchase WHERE cid=1
(Query 2 - find the 'club' with the highest 'qnty' for cid=1)
SELECT *
FROM
(SELECT club,
sum(qnty) AS t_qnty
FROM yrb_purchase
WHERE cid=1
GROUP BY club)results
ORDER BY t_qnty DESC
(Query 3 – combine the record from the above query with it’s cid)
SELECT cid,
temp.club,
temp.t_qnty
FROM yrb_purchase AS p,
(SELECT *
FROM
(SELECT club,
sum(qnty) AS t_qnty
FROM yrb_purchase
WHERE cid=1
GROUP BY club)results
ORDER BY t_qnty DESC FETCH FIRST 1 ROWS ONLY) AS TEMP
WHERE p.cid=1
AND p.club=temp.club
(Query 4) make sure there is only one record for cid=1
SELECT cid,
temp.club,
temp.t_qnty
FROM yrb_purchase AS p,
(SELECT *
FROM
(SELECT club,
sum(qnty) AS t_qnty
FROM yrb_purchase
WHERE cid=1
GROUP BY club)results
ORDER BY t_qnty DESC FETCH FIRST 1 ROWS ONLY) AS TEMP
WHERE p.cid=1
AND p.club=temp.club FETCH FIRST ROWS ONLY
To get the 'club' with the highest 'qnty' for customer 2, I would simply change the text cid=1 to cid=2 in the last query above. My query seems to always produce the correct results. My question is, how do I modify my query to get the results for all 'cid's from 1 to 45 in a single table? How do I get a table with all the cid values along with the club which sold that cid the most books, and how many books were sold within one tablei? Please keep in mind I am hoping you can modify my query as opposed to you providing a better query.
If you decide that my query is way too ugly (I agree with you) and choose to provide another query, please be aware that I just started learning SQL and may not be able to understand your query. You should be aware that I already asked this question: For common elements, how to find the value based on two columns? SQL but I was not able to make the answer work (due to my SQL limitations - not because the answer wasn't good); and in the absence of a working answer I could not reverse engineer it to understand how it works.
Thanks in advance
****************************EDIT #1*******************************************
The results of the answer is:
You could use OLAP/Window Functions to achieve this:
SELECT
cid,
club,
qnty
FROM
(
SELECT
cid,
club,
qnty,
ROW_NUMBER() OVER (PARTITION BY cid order by qnty desc) as cid_club_rank
FROM
(
SELECT
cid,
club,
sum(qnty) as qnty
FROM yrb_purchase
GROUP BY cid, club
) as sub1
) as sub2
WHERE cid_club_rank = 1
The inner most statement (sub1) just grabs a total quantity for each cid/club combination. The second inner most statement (sub2) creates a row_number for each cid/club combination ordering by the quantity (top down). Then the outer most query chooses only records where that row_number() is 1.

SELECT information from another query SQL

I am trying to select information from an already run query using SQL. I don't have the rights to create a view which I am aware would solve my problem. I have run the below (obfuscated) query which is throwing a number of errors:
SELECT
distinct(countValue),
count(countValue)
FROM
(
SELECT customer_identifier, count(distinct(2nd_customer_identifier)) AS countValue FROM table GROUP BY customer_identifier;
)
GROUP BY
distinct(countValue)
The subquery (below) is attempting to get a count of the unique payees for every customer:
SELECT
customer_identifier,
count(distinct(2nd_customer_identifier)) AS countValue
FROM table
GROUP BY aid
and the main query using that is attempting to get the counted values from the above table and count how many times each one occurs.
Any help would be much appreciated.
Can you logically replace it with the following? This will tell you how many multiple-payer situations you have.
SELECT
CountValue,
count(countValue) TotalRecords
FROM
(
SELECT
customer_identifier,
count(distinct([2nd_customer_identifier])) AS countValue
FROM table
GROUP BY customer_identifier
) a
GROUP BY countValue ;
Output will tell you something along the lines of:
There were 25 one-payer accounts
There were 17 two-payer accounts
There were 9 three-payer accounts
Etc.
If that's not what you want, please edit your question to describe the output you are after.

SQL Count() - Selecting the same row more than once

I'm currently re-working the size filter i built earlier this year for our website. The size filter query works off the stock_id's found in the products query. On occassions, the same product can appear many times, due to it being a single listing as well as appearing inside a mix and match listing.
Because the stock_id remains the same however, whenever i run a query using stock_id In (#products.stock_id#), i only get the one row, when because lets say products.stock_id equals 1234,1234,1235. 1234 will only be shown once rather than twice, how do i get this record to be counted twice? I know it's not the most straightforward of questions but i don't have much time to dedicate to this post unfortunately.
EDIT 1 - Size Filter Query
<cfquery datasource="#application.datasource#" name="size_filter">
Select size_id,
size_description,
size_count
From sizes
Inner Join (
Select stock_sizeid,
Count(*) As size_count
From stock
Where stock_id In (#valueList(products.stock_id)#)
And stock_sizeid Not In ('33','218')
And stock_instock > 0
Group By stock_sizeid
) As stock
On size_id = stock_sizeid
Order By size_description Asc
</cfquery>
Cheat, and JOIN to your id list (instead of using an IN clause):
<cfquery datasource="#application.datasource#" name="size_filter">
Select size_id,
size_description,
size_count
From sizes
Inner Join (Select stock_sizeid,
Count(*) As size_count
From stock
Join (Select stock_id
From (VALUES(#valueList(products.stock_id)#)) a(stock_id)) As ids
On ids.stock_id = stock.stock_id
Where stock_sizeid Not In ('33','218')
And stock_instock > 0
Group By stock_sizeid) As stock
On size_id = stock_sizeid
Order By size_description Asc
</cfquery>
To make VALUES() give rows instead of columns, the correct form is VALUES(1), (2), ...(n). I'm assuming valueList(...) is some client-side procedure that gets run when the statement gets prepared; you'll need to provide an equivalent function to produce this output.
(Note, I've never used coldfusion, so I don't know if this actually works. This type of thing works in most RDBMSs, although some complain)
What this is doing is turning your list into a virtual table, which has all your entries in it, so the JOIN will be assessed multiple times, as normal.

SQL Sum with Sub Query?

Thanks for any help in advance, I can't wrap my SQL skills around this one...
I have two tables like this:
Settings
Customerid ViewerLimit
1 50
2 50
Distribution
Customerid ServerIP
1 stream3
1 stream4
2 stream3
I want to calculate the load on each server. A customer divides the load if they have more than one server, so here customer 1 puts a load of 25 on each server. The result I'm trying to get is this:
ServerIP Load
stream3 75
stream4 25
I tried to do a sum function similar to this:
sum(viewerlimit/(count # of servers)) as load group by serverip
But I can't do a sub query within a sum function. There are many customers and possibly many servers per customer so it will become too complex to do manually. I appreciate any input.
Here is uninspired version with count in derived table:
select serverip, sum (viewerlimit/cast (ServerCount as float)) Load
from
(
select customerid, count(*) ServerCount from distribution group by customerid
) a
inner join settings
on a.customerid = settings.customerid
inner join distribution
on settings.customerid = distribution.customerid
group by serverip
Sql Fiddle to play around
UPDATE - an attempt at explanation
Derived tables are used to produce ad-hoc result sets that can be joined to main body of a query. It is placed in from clause and enclosed in parenthesis. You can use anything an ordinary select can use, top, order by, aggregate functions etc. The only thing you cannot use is correlation to a table in main body. Oh, and CTE. Derived table must be aliased.
In previous sample derived table 'a' selects counts of servers by customerid. Main body sees it as a table with CustomerId and ServerCount columns, ready to be used as any column from all listed tables. A join on customerid is performed between settings and 'a'. As this is 1:1 relation (both tables produce single row given a customerid), no duplication occurs.
How about doing a count of servers in a sub query and assign that to a query variable and then use that query variable inside the sum function?
select d.serverip, sum(s.viewerlimit/d.devider)
from (
select customerid, serverip, COUNT(serverip) over (partition by customerid) servercount
from distribution
) d
join settings s
on s.customerid=d.customerid
group by d.serverip

How to use results of one sql query within a sub-query

I have to answer the following question
"For each year in the database, list the year and the total number of
movies that were released in that year, showing these totals in
decreasing order. That is, the year(s) with the largest number of
movies appear first. If some years have the same number of movies,
show these in increasing order of year."
Currently I am using the code below to get the movies to group together, but am unable to get them to sort:
Select YearReleased, count(*)
from Movies
group by YearReleased
I wish to use something to order this and am trying to make a sub query that uses the results of the first query, along the lines of:
(select * from results order by count(*))
but so far I have been unsuccessful. How do I achieve this or is there a better way of getting the results in that order?
"Unsuccessful" isn't very useful, as opposed to actual error text -- and you aren't telling us which vendor's database you're running against, so we can't test. That said, the following should work:
select
YearReleased,
count(*) as movie_count
from movies
group by YearReleased
order by movie_count desc, YearReleased;
No subqueries needed!
Validated against SQLite 3.5.9; if running against something less standards-compliant (which SQLite is, except in very explicitly documented ways), your mileage may vary.
select *
from
(
Select YearReleased, count(*) as NumReleased
from Movies
group by YearReleased
)
order by NumReleased
select * from (select YearReleased, count(*) counter
from Movies
group by YearReleased
) a order by counter
May need a syntax change depending on your sql flavour.
in first query: select yearReleased, count(*) as 'count1'
in second: order by count1
Yep, with aggregates you can just put an alias for count(*) and it can be reffered as a column.