Select multiple fields on different rows with ONE query - php

With one MYSQL query only, how can I check if a buyer and a seller have both bought from each other ?
Table : purchase
purchase_id | seller | buyer
12 | 2 | 5
29 | 5 | 2
If the query returns a result (which would be the case here), then a specific div would appear on the page.

SELECT (COUNT(*) >= 2) AS Result
FROM purchase a
INNER JOIN purchase b
ON a.seller = b.buyer AND
a.buyer = b.seller
WHERE (a.seller = 2 AND a.buyer = 5) OR
(a.seller = 5 AND a.buyer = 2)
SQLFiddle Demo
just replace 2 and 5 with your variables.

Related

MySQL - Is it possible to merge select queries, so it doesn't have to be executed in while loop?

So i have a query which will get all information about matched rows where items are not visible.
Now inside while loop i had to use select count query to count how many not visible items every user has and it takes too much time if there are so many results in a loop.
Is there a way to query it without running select query inside while loop?
For example:
SELECT categories.name,
quality.name,
users.regdate,
categories.name,
items.name,
items.visible,
items.owner,
users.username
FROM items
LEFT JOIN users ON items.owner = users.id
LEFT JOIN categories ON items.category = categories.id
LEFT JOIN quality on items.category_quality = quality.id
WHERE items.visible = 'no'
Now in while loop to get number of items, i had to query
while($row = mysqli_fetch_assoc($sql))
{
$all_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']."";
$visible_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']." AND items.visible = 'yes'";
// rest of code here.
// when there are 200 items in loop executing time goes crazy
// (6+ secs, where with 1 item it's around 0.05)
}
Edit with example:
Some people asked to see what final code would be, I'll try to give the best i can.
Ignore left joins as this is not relavent, I just added those from the whole query.
Id | item name | owner | Visible
1 | Item 1 | 2 | no
2 | Item 2 | 2 | yes
3 | Item 3 | 2 | no
4 | Item 4 | 2 | no
5 | Item 5 | 2 | no
6 | Item 6 | 3 | no
7 | Item 7 | 3 | no
8 | Item 8 | 3 | no
9 | Item 9 | 4 | no
10 | Item 10 | 4 | no
In while loop for every user it should count how many rows user owns.
For example:
user 2 owns 5 rows total and 4 hidden, ($all_items_by_user will count everything, while $visible_items_by_user will count only 1)
user 3 owns 3 rows,
user 4 owns 2 rows.
How to count per user items because if i do it outside of while loop, it will count only for first user, not for every single user.
The final result should be
while($row = mysqli_fetch_assoc($sql))
{
$all_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']."";
$visible_items_by_user = "SELECT COUNT(items.name)
FROM items
WHERE items.owner = ".$row['owner']." AND items.visible = 'yes'";
echo $row['owner'] . "(Visible items: number | All items: number";
// Output: 2 (Visible items: 1 | All items: 5)
}
This assumes that you only care about the counts per user and that you do not care bout any items specific information
SELECT items.owner,
COUNT(items.name) AS itemCount,
SUM( CASE WHEN items.visible = 'yes' AND item.name IS NOT NULL
THEN 1 ELSE 0 END) AS visibleCount
FROM items
GROUP BY items.owner
Then you just loop through each row, which will give you the user, total count for that user, and visible count for that user.
DEMO
You could avoid queries in loop using a join for aggreated result subqquery
SELECT categories.name,
quality.name,
users.regdate,
categories.name,
items.name,
items.visible,
items.owner,
users.username,
ifnull(t.count_name,0),
ifnull(t.count_visible_name,0)
FROM items
LEFT JOIN users ON items.owner = users.id
LEFT JOIN categories ON items.category = categories.id
LEFT JOIN quality on items.category_quality = quality.id
LEFT JOIN (
select items.owner
, COUNT(items.name) count_name
, sum( case when items.visible = 'yes' AND item.name is not null
then 1 else 0 end) count_visible_name
from items
group by items.owner
) t on t.owner = items.owner
be sure you have proper composite index
on table items column(owner, category, category_quality)

Left JOIN give incorrect total sum result [duplicate]

This question already has an answer here:
MySQL SUM() giving incorrect total
(1 answer)
Closed 6 years ago.
I have two table on (daily_book and extra_cost) so structure is
daily_book
db_id | refund
1 | 7161
2 | 5980
extra_cost
ec_id | db_id | cost
1 | 1 | 156
2 | 1 | 123
3 | 2 | 100
4 | 2 | 120
So I get total refund value and total cost value in one row.
So my query is
$sql = "SELECT SUM(d.refund) AS refund, SUM(e.cost) AS e_cost FROM `daily_book` d LEFT JOIN extra_cost e ON (d.db_id = e.db_id) WHERE d.db_id > 0";
I got result is 26,282 for refund and 499 for total cost; that's incorrect.
I want result is 13,141 for refund and 499 for total cost.
There is no mystery here. You are aggregating multiple rows for the refund. You need to do the aggregations separately. In MySQL, this is a bit cumbersome, but here is one method:
SELECT dd.refund, SUM(e.cost) AS e_cost
FROM daily_book d LEFT JOIN
extra_cost e
ON (d.db_id = e.db_id) CROSS JOIN
(SELECT SUM(d.refund) as refund FROM daily_book d WHERE d.db_id > 0) dd
WHERE d.db_id > 0;

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.

Subselect with multiple results

I'm trying to do return results from one table based on multiple results on another. Here's the setup:
Table A: "accounts"
id | fname | other_id
1 | test | 500
2 | test2 | 505
3 | test3 | 500
4 | test4 | 540
5 | test5 | 500
Table B: "transactions"
id | account_id |
1 | 1
2 | 4
3 | 2
4 | 1
5 | 3
6 | 2
What I'm trying to accomplish is, return all id's from transactions where account_id = the id in table A WHERE other_id = a certain value.
To do write it out manually it would look like this:
So for example if other_id = 500.
1) get records from accounts where other_id = 500 (will be multiple results, in this case, 1, 3 and 5)
2) get records from transactions where account_id = 1 OR account_id = 3 OR account_id = 5
I've tried a few different subselects but can't seem to come up with what I'm looking for.
I of course could just break this up into a loop using PHP but I'd rather use a single query for efficiency.
No subselect required, just a simple join.
select * from accounts a, transactions t where t.account_id=a.id and other_id=500
select t.id
from accounts as a
inner join transactions as t on a.id = t.account_id
where a.other_id=500
If i understand you right, you want this.
SELECT b.id
FROM accounts AS a
LEFT JOIN transactions AS b ON b.account_id = a.id
WHERE other_id = 500

How to make a order list of raw database data

I have a big database which is already filled and contains order data. I have a table named order which contains all the orders.
I need to make a list of all the ordered products which are the same. It's something like this:
My data in the database
id = 1 | orderid = 1 | product = A
id = 2 | orderid = 1 | product = A
id = 3 | orderid = 1 | product = B
id = 4 | orderid = 1 | product = B
id = 5 | orderid = 1 | product = B
id = 6 | orderid = 2 | product = A
In short:
order 1 has 2 product A and 3 product B
order 2 has 1 product A and 2 product B and 4 product C
order 3 has 3 product A and 3 product C
I would like to make a summary:
product A ordered 6 times
product B ordered 5 times
product C ordered 7 times
I can't find a way to iterate through the products which are ordered one by one. How can I count this or group them. I can't add an extra table because the database is not under my supervision.
You can do this with one query to your DB. In MySql:
SELECT product, COUNT(*) as count FROM test GROUP BY product
It returns two columns: first - product name, second - count.

Categories