Repeat a query over the parameter list - sql

I would like to iterate the same query while using different parameter values from a predefined list.
Say, I have a table with two columns. The first columns contains customer name. The second column contains customer spending.
###CUSTOMER; SPENDING###
customer1; 1000
customer2; 111
customer3; 100
customer1; 323
...
I know the complete list of customers: customerlist = {customer1, customer2, customer3}.
I would like to do something like:
Select sum(spending)
from mytable
where customer = #customerlist
The query should compute the sum of spending for each customer defined in the customer list. I have found some examples of sql procedures with stored parameters but not the case with one parameter of multiple values.
Thank you
P.S. This is just a hypothetical example to illustrate my question (I know it would be much more effective to use here a simple group by).

You can use nested query like this
SELECT CustomerList.CustomerName Cust, isnull((SELECT SUM(Spending) CustSpending
FROM Customer
WHERE Customer.CustomerName = CustomerList.CustomerName),0)
FROM CustomerList

This would normally be done using GROUP BY:
Select customer, sum(spending)
from mytable
group by customer;
GROUP BY is a very fundamental part of SQL. You should review your knowledge of SQL so you understand how to use it.

Related

How can I select multiple columns and group them by 2 or 3 of them in SQL?

I got stuck on a simple task and it sounds like this: I need to write a select query, so it returns me 5-6 columns grouped by 2-3 of them.
So, for example it would look like this:
Select SSN,ClientTypeId,Id,Count(SSN)
From Contact
Where ClientTypeId = 'GUID for active clients'
Group By SSN,ClientTypeId
All I want to do is to get a list of customers (identified by SSN) who has several active contacts.
I have found examples where multiple columns were grouped by one columns, but couldn't find something like my case. Thank you!
Your GROUP BY needs to go after your WHERE clause and all non-aggregated columns need to be in your GROUP BY e.g.
Select SSN,ClientTypeId,Id,Count(SSN)
from Contact
where ClientTypeId = 'GUID for active clients'
Group By SSN,ClientTypeId,Id

How do I write an SQL query whose where clause is contained in another query?

I have two tables, one for Customer and one for Item.
In Customer, I have a column called "preference", which stores a list of hard criteria expressed as a WHERE clause in SQL e.g. "item.price<20 and item.category='household'".
I'd like a query that works like this:
SELECT * FROM item WHERE interpret('SELECT preference FROM customer WHERE id = 1')
Which gets translated to this:
SELECT * FROM item WHERE item.price < 20 and item.category = 'household'
Example data model:
CREATE TABLE customer (
cust_id INT
preference VARCHAR
);
CREATE TABLE item (
item_id INT
price DECIMAL(19,4)
category VARCHAR
);
# Additional columns omitted for brevity
I've looked up casting and dynamic SQL but I haven't been able to figure out how I should do this.
I'm using PostgreSQL 9.5.1
I'm going to assume that preference is the same as my made up item_id column. You may need to tweak it to fit your case. For future questions like this it may pay to give us the table structures you are working with, it really helps us out!
What you are asking for is a subquery:
select *
from item
where item_id in (select
preference
from
customer
where id = 1)
What I would suggest though is a join:
select item.*
from item
join customer on item.item_id = customer.preference
where item.price<20 and
item.category='household'
customer.id = 1
I decided to change my schema instead, as it was getting pretty messy to store the criteria in preferences in that manner.
I restricted the kinds of preferences that could be specified, then stored them as columns in Customer.
After that, all the queries I wanted could be expressed as joins.

Querying records that meet muliple criteria

Hi I’m trying to write a query and I’m struggling to figure out how to go about it.
I have a suppliers table and a supplier parts table I want to write a query that lists suppliers that have specified related Parts in the supplier parts table. If a supplier doesn’t have all specified related parts then they should not be listed.
At the moment I have written a very basic query that lists the supplier if they have a related supplier part that meets the criteria.
SELECT id ,name
FROM
efacdb.dbo.suppliers INNER JOIN [efacdb].[dbo].[spmatrix] ON
id = spmsupp
WHERE spmpart
IN ('ALUM_5083', 'ALUM_6082')
I only want to show the supplier if they have both parts related. Does anyone know how I could do this?
Use a subquery with counting distinct occurences:
select * from suppliers s
where 2 = (select count(distinct spmpart) from spmatrix
where id = spmsupp and spmpart in ('ALUM_5083', 'ALUM_6082'))
As a note, you can modify your query to get what you want, just by using an aggregation:
SELECT id, name
FROM efacdb.dbo.suppliers INNER JOIN
[efacdb].[dbo].[spmatrix]
ON id = spmsupp
WHERE spmpart IN ('ALUM_5083', 'ALUM_6082')
GROUP BY id, name
HAVING MIN(spmpart) <> MAX(spmpart);
If you know there are no duplicates, then having count(*) = 2 also solves the problem.

Beginning SQL group by and AVG

I am trying to pull information from two columns titled clientstate and clientrevenue in my table. I want clientstate to show up as the state, and have only distinct names in it, and under client revenue I want the average revenue per state, and that will only show up if there are at least two clients from that state. I am very new at this, so what I have is pretty iffy:
SELECT clientstate, clientrevenue
FROM client
GROUP BY clientrevenue
HAVING COUNT (*) >=2;
Where am I going wrong here?
SELECT clientstate AS [State]
, AVG(clientrevenue) AS [Average Revenue]
FROM client
GROUP BY clientstate
Grouping by ClientRevenue will try to group similar values and that doesn't have a logical sense.
First, in order to get distinct states, clientstate column needs to be used in the GROUP BY statement.
Thus, the code would be :
SELECT clientstate, AVG(clientrevenue)
FROM Source_Table
GROUP BY clientstate --this would get you distinct states
Now, considering the 2 clients per state, it's rather a condition than a HAVING statement. HAVING statement limits your query results according to the aggregate function you are using. For instance, in the code aforementioned, the aggregate function is AVG(clientrevenue). So, we can only use it in HAVING. we can not add count(*) unless it was used in SELECT.
So, you need to add it as a condition like
SELECT clientstate, AVG(clientrevenue)
FROM Source_Table A
WHERE (SELECT count(DISTINCT client_ID) FROM Source_Table B
WHERE A.clientstate = B.clientstate) >= 2 --Condition
GROUP BY clientstate --this would get you distinct states

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