Complex SELECT MySQL statement - php

I have run into an issue selecting data from my MySQL database.
For example, I have a table with the following columns & tables:
Table name: farming
id | animal | amount | food
----------------------------
1 | Cow | 10 | Grass
12 | Sheep | 19 | Grass
23 | Lion | 1 | Everything
29 | Lamb | 3 | Grass
102| Pig | 8 | Everything
...
I want to get the amount from all the rows that match the food type of a selected id.
E.g. If I choose id: 102 then it would get the amount from ALL rows where the food = 'Everything'
SELECT amount FROM farming WHERE food = '".$_GET['food']."' **IS THE SAME TYPE AS IT IS IN** id = '1'"; // This should select 10, 19 and 3 from amount (as id = 1's foodtype is Grass, so it should select amount from all rows where foodtype = grass.
** is where I'm facing issues, I've tried various statements and can't seem to get it to work.

You could use group by clause which will sum up all value from amount column whre food = 'Grass'
SELECT SUM(amount) ammount FROM farming
WHERE food = (select food FROM farming where id = 102)
GROUP BY food

This should do the trick
select amount
from farming
where food = (
select food
from farming
where id = 1
)

Related

MySQL Select second count of pre selected results

Hello I am trying to make a Select where the uses chooses department and would like to have clause WHERE this department is first, let's say we select 10 results from department: Taxes and then make a SUM SELECT of fee WHERE status = 1. Which results be selected based on the first select All the results are coming from the same table.
| id | department | status | fee |
----------------------------------
| 1 | tax | 1 | 20 |
| 2 | tax | 2 | 20 |
| 3 | tax | 1 | 20 |
| 4 | accounting | 1 | 20 |
So I would like to select if department is choose as tax, and status is 1 the sum of FEE columns which should be 40
So far my Select query looks like this:
SELECT P.id, P.fee, (SELECT SUM(P.fee) FROM cases P WHERE status = 1) as fee_USD
FROM cases P WHERE 1";
if (!empty($department)) { $sql .= " AND P.department = '$department'"; }
the last line is checking if department is given as select option. there are other options as well but to make it simple I have pasted only this part of it. Any help is welcome.
In the Current Selection Fee is = 80
You have to add correlation to your query:
SELECT P1.id, P1.fee,
(SELECT SUM(P2.fee)
FROM cases P2
WHERE P2.department = P1.department AND status = 1) as fee_USD
FROM cases P1
WHERE 1 ...
This way the subquery will return the SUM of only those records which are related to the current record of the main query.

Is it possible to add more text to a text from MySQL?

Okay so I am trying to make this form for teams. Something like:
Football Club Name | W-W-L-D-W (W=win, D=draw, L=lose)
The way I thought I will do this is by adding text. For example, there is this match between FC Apple - FC Banana. Banana wins 0-1. In the team's row from the teams table, the "form" column is modified, adding "-W". Another match for Banana, with Kiwi, which they lose. Again adding "-L" to the column. So now the column is "-W-L". Is this possible?
I've thought about making 5 colums, lastmatch, lastmatch2, ... lastmatch5. When a team wins, lastmatch5 is W. If lastmatch4 is null and the team loses, lastmatch4 will be L. If all lastmatch columns are filled, then make lastmatch1 = lastmatch2, 2=3, 3=4, 4=5 , 5 = null, and its filled by the result.
But this is very complicated... Thats why I thought about the first method.
Any other methods? What do you think?
First, to answer your question, you could just grab the current content, like W-W-L-D, from the column, add the recent outcome, like -W, and then update the column with the new string - W-W-L-D-W. But I don't suggest doing it this way. Storing individual records in a long string is probably not the best idea. Instead, create separate relational tables. This is just off the top of my head, but I would consider doing something more like this:
Table: Football_club
+========================+
| Id | Name |
|---------|--------------|
| 1 | Apple |
| 2 | Banana |
| 3 | Kiwi |
+========================+
//This table stores each Football club's basic info
Table: Matches
+================================================+
| Id | Date | Team1_id | Team2_id |
|-------|-----------|-------------|--------------|
| 1 |2014-05-14 | 1 | 2 |
| 2 |2014-05-15 | 1 | 3 |
| 3 |2014-05-16 | 2 | 3 |
+================================================+
//This table stores basic info about each match.
Table: Match_outcomes
+==================================+
| Id | Match_id | Winner_id |
|-------|--------------|-----------|
| 1 | 1 | 2 |
| 2 | 2 | NULL |
| 3 | 3 | 3 |
+==================================+
//This table stores match outcomes.
//A winner ID of NULL would mean it was a draw (you could also use 0 or -1 or some other value that is not a team id)
This way, you can always get the number of wins, losses, and draws for any team, or add matches and match outcomes pretty easily.
For example, to get number of wins for team $id:
(I haven't tested this, but I think it would work)
SELECT
COUNT(mo.id) AS wins
FROM match_outcomes mo
JOIN matches m ON m.id = mo.match_id
AND (m.team_id1 = $id OR m.team_id2 = $id)
WHERE mo.winner_id = $id
GROUP BY mo.winner_id
Update - Been messing around with this... here's a sample query to get all wins, losses, and draws for each team using the above DB:
SELECT
fc.name,
SUM(IF(mo.winner_id=fc.id, 1, 0)) AS wins,
SUM(IF(mo.winner_id!=fc.id, 1, 0)) AS losses,
SUM(IF(ISNULL(mo.winner_id), 1, 0)) AS draws
FROM match_outcomes mo
JOIN matches m ON m.id = mo.match_id
JOIN football_clubs fc ON fc.id = m.team1_id
OR fc.id = m.team2_id
GROUP BY fc.name
See this SQL Fiddle
This is just a rough idea - hopefully it's helpful!

mysql count function problems

I have a table which is formatted as:
id | food | userID | beerID
I am trying to select all the foods for a given beerID and a count of repeats. SO if there are 3 entries for pizza I get results like:
food | beerID | count
pizza | 34 | 2
hot wings | 34 | 1
pasta | 34 | 5
Does this work? I am a bit confused on using the count with the group by.
select food, beerID , count() where beerID = 34 group by food
Give the count a parameter.
select food, beerID, count(food) from tablename as num where beerID = 34 group by food;
Footnote: "does this work" is a bad question. You'll 100% chance be rebutted with "did you not try it..?"
As noted in the comments you aren't selecting from a specific table, so it will error out
SELECT food, beerID, count(1) as beerCount
FROM tablename
WHERE beerID=34
GROUP BY food;

SQL for a Household Bill splitting db

I'm trying to build a mySQL database for a PHP page that will allow users to enter the cost of a bill and select who in the house it is split with. The problem I'm having is I can't figure out how to calculate the total owed between residents, taking account of what they have paid and what they need to pay someone else.
I want it to be able to handle variable numbers of users 'residents' so have designed the tables like so:
Users Table:
UserID | User
-------+---------
1 | Jon
2 | Boris
3 | Natalie
Bills Table:
BillID | BIll | Amount | Paid By (UserID F.Key)
-------+--------+----------+--------------
1 | Gas | £30.00 | 1 (Jon)
2 | Water | £30.00 | 1 (Jon)
3 | Tax | £60.00 | 2 (Boris)
4 | Phone | £10.00 | 2 (Boris)
So this table shows that the Phone Bill was £10.00 and Boris paid the Phone company for it.
Bills-Users Liabilities Junction Table:
UserID_fKey | BillID_fKey
------------+--------------
1 (Jon) | 1 (Gas)
2 (Boris) | 1 (Gas)
3 (Nat) | 1 (Gas)
1 (Jon) | 2 (Water)
2 (Boris) | 2 (Water)
3 (Nat) | 2 (Water)
1 (Jon) | 3 (Tax)
2 (Boris) | 3 (Tax)
1 (Jon) | 4 (Phone)
2 (Boris) | 4 (Phone)
The Bill-Users table is used to describe who is liable for each of the bills. So, for example Natalie never uses the phone so doesn't need to pay Boris anything for it. The phone bill therefore is split between Borris and Jon. Jon therefore owes Boris £5.
I think this is the best way to do it but I can't work out how to generate a table for each user when they login that shows what they owe one another. To do this (for example) I need to add up everything Jon has paid for, what everyone has paid for on behalf of Jon and work out the balance. Obviously this needs to scale so that there could be 3 or more users in the system.
This is the result I would like to get to:
(eg: Logged in as Jon)
User | Amount Owed
---------+-------------
Boris | -£15.00
Natalie | £20.00
Many Thanks in advance.
you need an owe field in your bill table in order to do bottom bit.
select individual user
SELECT Users.User, Bills.BIll, Bills.owe, Bills.Amount
FROM Users
LEFT JOIN Bills ON Users.UserID = Bills.UserID
WHERE Users.UserID =1
select all users
SELECT Users.User, Bills.BIll, Bills.owe, Bills.Amount
FROM Users
LEFT JOIN Bills ON Users.UserID = Bills.UserID
LIMIT 0 , 30
select all users sum of paid
SELECT Users.User, Bills.BIll, sum(Bills.owe), sum(Bills.Amount), sum(Bills.owe)- sum(Bills.Amount) as arrears
FROM Users
LEFT JOIN Bills ON Users.UserID = Bills.UserID
GROUP BY Users.UserID;
demo
In the end I achieved this by using a function. It probably wouldn't scale to 100's of users very well but still gives me the flexibility I wanted. I'm trying to start an SQLFiddle to demo it but having issues.
Set #CurrentUser = '1' (Jon)
Select User, funcAmountOwed(#currentuser,UserID) from Users
WHERE UserID != #CurrentUser;
Returns:
User | Amount Owed
---------+-------------
Boris | -£15.00
Natalie | £20.00
The function is something along the lines of:
funcAmountOwed(#CurrentUser, #CurrentDebtor);
SET #AmountPaidByCurrentUser = (
Select SUM(Amount) from Bills b
INNER JOIN BillsUsers bu ON b.BillID = bu.BillID_fkey
WHERE b.PaidBy = #CurrentUser and bu.UserId_fkey = #CurrentDebtor)
SET #AmountPaidByDebtor = (
Select SUM(Amount) from Bills b
INNER JOIN BillsUsers bu ON b.BillID = bu.BillID_fkey
WHERE b.PaidBy = #CurrentDebtor and bu.UserId_fkey = #CurrentUser)
RETURN #AmountPaidByCurrentUser - #AmountPaidByDebtor;
I had to nest another function in there to divide the Amount by the Number of people the Bill was split between too but as above I can't remember that from memory without SQLFiddle.

Mysql - How to query a table that may have multiple entries in each cell and get a result with single values in each cell

Name Hobby
John | Fishing,Traveling
Mary | Reading,
Tom | Music,
Kate | Cooking,Reading
George | Traveling,
Peter | Fishing,
Lisa | Cooking,
I want to select this table
Hobby Count
Fishing | 2
Traveling | 2
Reading | 2
Music | 1
Cooking | 2
How can I do that?
Use your table properly instead of cramming multiple hobby values into a single column. You should have:
John | Fishing
John | Traveling
Mary | Reading
Tom | Music
Kate | Cooking
Kate | Reading
George | Traveling
Peter | Fishing
Lisa | Cooking
Then you can do:
select hobby
, count(*) count
from tablename
group by hobby
order by hobby
I would do it like #Wes
or if its not possible i'd do it in PHP
$result = array();
$sql = 'SELECT Hobby, count(*) as cnt FROM youttable GROUP BY Hobby';
foreach ($conn->query($sql) as $row) {
foreach(explode(',',$row['Hobby']) as $hobby) {
$result[$hobby] += $row['cnt'];
}
}
Generally what you would do is have a separate table for hobbies.
So your first table would be consisted of: nameID, name.
And your second table would consist of: hobbyID, nameID, description.
Once you have it set up like that, you use nameID to link the two tables together.
SELECT * FROM nameTable, hobbyTable WHERE nameTable.nameID = hobbyTable.nameID
And when you have that you can use count() on the hobbyTable to get the quantities.
SELECT Hobby, Count(*) FROM myTable ORDER BY Hobby GROUP BY Hobby

Categories