for loop functionality in mysql query - mysql

this is MYSQL query question
First, let say we have
[ALL_MENU]
name
-----
pasta
pizza
and people ordered
ordered
customer name status
john pasta delivered
kim pasta delivered
john pizza delivered
john pasta delivered
I want to go through the ordered table and find anyone who ordered all the menu
In this example, kim only ordered pasta so it should not be included
but john ordered both pasta and pizza, so it should be included on the result.
is There any type of query to do the 'For loop' ability?
thank you
(ps, right now I only allow to use
some basic function command from mysql
group by , create view, exists , all, not exist , unique such and such )
=========================================================================
Ok, From the answer
the count number of all menu thing is work when (customer,name) are the primary key
But what if i added the data column, and primary key as (customer,name,data)
customer name status date
john pasta delivered 3/4
kim pasta delivered 3/5
john pasta delivered 3/5
this is the new column i made
john ordered the only pasta with 2 different date,
but johns number of order count as 2.
so count method will not work for this
How do we fix this problem?

The functionality of a for loop is a cursor. (FYI, most DBMS have such a construct.)
But never use a cursor when a plain old query will do just fine.
Here is one possible solution:
SELECT customer
FROM ordered
GROUP BY customer
HAVING COUNT(DISTINCT name) = (SELECT COUNT(*) FROM all_menu)
(This assumes that all names in ordered are found in all_menus, e.g. there is foreign key. If not, you'll have to add JOIN all_menu ON ordered.name = all_menu.name in the FROM clause.)
EDIT: "Simple"(!) commands only:
SELECT customer
FROM ordered o1
WHERE NOT EXISTS (
SELECT * FROM all_menu
WHERE name NOT IN (SELECT name FROM ordered o2 WHERE o1.customer = o2.customer)
)

Related

Sum on multi-joined tables

I have 4 tables
customers
sales
sale_items
stock_items
I want to list all my customers. For each customer I want the total amount purchased - a field that I want the sql query to create (xxx as totalSales)
I tried selecting customers as the primary table and joining other tables on it. I tried selecting sales as the primary table and also the sale_items. I kind of got the correct sum calculation but it will show me the first customer first.
This is what my tables look like:
*TABLE customers*
id
customer_name
email
*TABLE sales*
id
customer_id
transaction_date
*TABLE sale_items*
id
sale_id
stock_item_id
*TABLE stock_items*
id
item_name
price
I want to
Create a list of all customers, sorted by the customer with the most sales (in value) first. Not the count of the sales, but the total amount (sales value) of the sales
Display the items purchased per customer under the customer name. This would not be per order, but for all sales. So if a tin of coffee was purchased by customer X, over a count of 4 orders each, the tin of coffee would display 4 times. Though if possible I'd like the items listed a-z.
I have inner joined the tables on each other, so I would get a list of all transactions. I've tried SELECT * FROM customers, tried FROM sales, tried from sale_items. I've tried GROUP_BY customer_id, but then I would get incorrect counts.
I want to display the data as such.
CUSTOMER ITEMS TOTAL VALUE
John Doe Coffee
Milk
Tea
Milk
Bread
Coffee 500
Jane Doe Coffee
Milk
Coke 350
Denver Doe Coffee
Milk
Bread
Bread 125
I don't want to use PHP and make a query for every single "thing". I am trying to run one or two queries.
I don't think you're going to be able to quite get them in separate rows like you're showing (unless you look into the ROLLUP function), but that's probably not a requirement for you.
I think you should use GROUP_CONCAT which is an aggregation function sort of like SUM but it creates a comma separated list out of all of the values:
SELECT
*
SUM(sale_amount) as total_sales,
GROUP_CONCAT(item_name) as item_names
FROM customers c
JOIN sales s USING (customer_id)
JOIN sale_items si USING (sale_id)
JOIN stock_items sit USING (stock_item_id)
GROUP BY customer_id
What you should see as a sample row is:
Denver Doe Coffee,Milk,Bread,Bread 125
(I had to make up some column names, like sale_amount, but you must have those in there I'm sure. You'll have to make some adjustments in those names and maybe in how I did the joins as well, but this should work with some changes if I'm understanding your needs).

Excluding unique ID in a query if at least one criteria is met

I'm having this problem which I'm unsure how to resolve.
Here's the situation : I want to get a list of all individuals who have not completed a survey. It is however possible for someone to start/complete multiple surveys.
Therefore, I want the list of individuals who have not completed at least one survey.
Here's what my query looks likes to get the list of people with incomplete surveys :
SELECT Survey.UserID, Survey.Fullname
FROM [...]
WHERE Survey.SurveySubmitted = 0 -- 0 = Unsubmitted, 1 = submitted
Now this is what the database could look like
UserID Fullname SurveySubmitted
1 John Smith 0
2 Jane Doe 1
3 Tom Glass 0
3 Tom Glass 1
Now the above query will select both John Smith and Tom Glass. However, since Tom Glass already completed at least one survey, he should be excluded.
Any ideas to proceed? It most likely needs a SELECT within another SELECT but I'm having trouble picturing it.
You could check for the user not in the user that have submited/completed
select Survey.UserID, Survey.Fullname
from [.....]
where UserID NOT IN (
SELECT Survey.UserID, Survey.Fullname
FROM [...]
WHERE Survey.SurveySubmitted = 1
)
You should group by whatever uniquely identifies a User/Survey combination and then sum the # of surveys that have been submitted. You can then use a having clause to filter out rows > 0:
select *
from Survey
group by UserId, FullName
having sum(SurveySubmitted) = 0;
SQLFiddle Example

Query: COUNT in Access To Only Count Unique Values

I have a table like so:
Customer Purchase Date Product
Frank 7/28/2015 Hammer
Bob 7/29/2015 Shovel
Bob 7/29/2015 Pickaxe
Bill 7/30/2015 Pliers
The Purchase Date field records a new entry for every purchase. So, if in one visit a customer purchases four items, my database creates four entries each with the same date.
I'm trying to write a query that displays the numbers of visits for each customer. Output like so:
Frank 1
Bob 1
Bill 1
But when I use the COUNT function on the date in my query, it returns:
Frank 1
Bob 2
Bill 1
I want my query to only count unique dates, but the COUNT function doesn't work. Everywhere I read, it also says that the SQL COUNT (Distinct) doesn't work in Access. Access help says that if I set the Query Properties to Unique Values "Yes", it should only return unique values, but it doesn't work. I tried Unique Record "Yes" also, but that didn't work either.
Please help! Thanks!
Try this:
select Cust, count(cust) as CustomerCount
from (Select Distinct Table1.Customer as cust, Table1.PurchaseDate
from Table1)
group by cust

Return value from within a range in SQL Server 2008

I have two tables, one where it contains members & their cardnumbers, and outlet table which identifies the cardnumber ranges per outlet. I want to know which store the cardnumber the member has belongs to.
Members Table
MemberID Cardnumber FirstName LastName
1 123456123 John Doe
2 123456245 Sarah Smith
Outlets Table
OutletID OutletName StartCardNumber EndCardNumber
1 Balmain Store 123456100 123456200
2 Sydney Store 123456201 123456300
I can't think of a script which I can bring back the following information without having to
create a temp table first. Is there an easier way?
CardNumber FirstName LastName OutletName
123456123 John Doe Balmain Store
123456245 Sarah Smith Sydney Store
It's very simple. You join on a range using inequalities in addition to equalities.
SELECT
M.CardNumber,
M.FirstName,
M.LastName,
O.OutletName
FROM
dbo.Members M
INNER JOIN dbo.Outlets O
ON M.CardNumber >= O.StartCardNumber
AND M.CardNumber <= O.EndCardNumber
This is the same as M.CardNumber BETWEEN O.StartCardNumber AND O.EndCardNumber but I wanted to draw out the inclusive endpoints of your scheme using >= and <=. BETWEEN is not always suitable because very often the end value is exclusive requiring <, but not in this case.
Try this out right now online!

find out count of comma based value in MySql

I have two tables.
Table Emp
id name
1 Ajay
2 Amol
3 Sanjay
4 Vijay
Table Sports
Sport_name Played by
Cricket ^2^,^3^,^4^
Football ^1^,^3^
Vollyball ^4^,^1^
Now I want to write a query which will give me output like
name No_of_sports_played
Ajay 2
Amol 1
Sanjay 2
Vijay 2
So what will be Mysql query for this?
I agree with the above answers/comments that you are not using a database for what a database is for, but here is how you could calculate your table from your current structure in case you have no control over that:
SELECT Emp.name, IF(Played_by IS NULL,0,COUNT(*)) as Num_Sports
FROM Emp
LEFT JOIN Sports
ON Sports.Played_by RLIKE CONCAT('[[:<:]]',Emp.id,'[[:>:]]')
GROUP BY Emp.name;
See it in action here.
UPDATE: added the IF(Played_by IS NULL,0,COUNT(*)) instead of COUNT(*). This means that if an employee doesn't play anything they'll have a 0 as their Num_Sports. See it here (I also added in those ^ characters and it still works.
What it does is joins the Emp table to the Sports table if it can find the Emp.id in the corresponding Played_by column.
For example, if we wanted to see what sports Ajay played (id=1), we could do:
SELECT *
FROM Emp, Sports
WHERE Sports.Played_by LIKE '%1%'
AND Emp.id=1;
The query I gave as my solution is basically the query above, with a GROUP BY Emp.name to perform it for each employee.
The one modification is the use of RLIKE instead of LIKE.
I use RLIKE '[[:<:]]employeeid[[:>:]]' instead of LIKE '%employeeid%. The [[:<:]] symbols just mean "make sure the employeeid you match is a whole word".
This prevents (e.g.) Emp.id 1 matching the 1 in the Played_by of 3,4,11,2.
You do not want to store your relationships in a column like that. Create this table:
CREATE TABLE player_sports (player_id INTEGER NOT NULL, sport_id INTEGER NOT NULL, PRIMARY KEY(player_id, sport_id));
This assumes you have an id column in your sports table. So now a player will have one record in player_sports for each sport they play.
Your final query will be:
SELECT p.name, COUNT(ps.player_id)
FROM players p, player_sports ps
WHERE ps.player_id = p.id
GROUP BY p.name;