Searching multiple databases to output lowest value - php

$query = mysqli_query($mysqli, "SELECT product_name ,MIN(product_price) product_price,link FROM(
select jumia.product_name,jumia.product_price,jumia.product_image,jumia.link from jumia INNER JOIN
jumia ON jumia.id = olx.id
where product.name like '%{$search}%'
UNION
select olx.product_name,olx.product_price,olx.product_image, olx.link from olx INNER JOIN
olx ON olx.id = jumia.id
where product.name like '%{$search}%')Minim
GROUP BY product_name,product_image
");
I am trying to create a query from two tables with similar column names as displayed above that will allow me to display the rows between the two tables that have the lowest price.
For example, if product_name called mattresses is searched the matching item in my database whose price is lower between the two table names should be displayed. Some help would be appreciated

I think this is the general idea of what you're trying to do:
SELECT id, price
FROM (SELECT id, price FROM T1 WHERE price = (SELECT min(price) FROM T1)
UNION
SELECT id, price FROM T2 WHERE price = (SELECT min(price) FROM T2)
) AS M
ORDER BY price ASC
LIMIT 1

Ended up changing the code and removing the ordering at the end and this finally worked. I hadn't properly linked my database using foreign keys, and changed my code to reflect this.
$query = mysqli_query($mysqli, "
SELECT product_name
, MIN(product_price) product_price
, link
FROM
( select j.product_name
, j.product_price
, j.link
from jumia j
JOIN olx
ON j.categoryID = olx.categoryID
where j.product_name like '%{$search}%'
UNION select olx.product_name
, olx.product_price
, olx.link
from olx
JOIN jumia
ON jumia.categoryID = olx.categoryID
where olx.product_name like '%{$search}%'
) x
");

Related

Multiple Counts in MYSQL PHP Query

I'm trying to create a leaderboard but i'm not sure how to do the mysql query.
I would like to count all the levels from a player in the skills table and get the total Level and count all the experience from a player in the experience table and get the Total Exp along with displaying the persons name from the users column.
There is 3 tables factions_mcmmo_users, factions_mcmmo_experience, factions_mcmmo_skills.
This is what i have so far but it doesn't work:
$sql = ("SELECT a.id,
(SELECT COUNT(*) FROM factions_mcmmo_experience WHERE user_id = a.id) as TotalXP,
(SELECT COUNT(*) FROM factions_mcmmo_skills WHERE user_id = a.id) as TotalLevel
FROM (SELECT DISTINCT id FROM factions_mcmmo_users) a LIMIT 10;");
Any help would be very appreciated
EDIT: I have it working now but i'm unsure if its the most efficient way to do things so if anyone could help me out if theres a better way, it would mean a lot.
I would also like to know if it's possible to display the total exp and level with commas if the number is in the thousands for example: total level 5,882 and total xp 582,882
EDIT 2:
I have figured out how to format the numbers but still don't know if my code is efficient
$sql = ("SELECT id, user,
(SELECT FORMAT(Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy),0) FROM factions_mcmmo_skills b WHERE b.user_id = a.id) as TotalLevel,
(SELECT FORMAT(Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy),0) FROM factions_mcmmo_experience c WHERE c.user_id = a.id) as TotalXP
FROM (SELECT id, user FROM factions_mcmmo_users) a group by id ORDER BY TotalLevel DESC, TotalXP DESC LIMIT 10;");
EDIT 3
Updated code from scaisEdge but was displaying everyones level as 1 and XP as 1, so i changed count(*) changed to sum, added an order By TotalLevel in Descending order and that seems to have worked but i can't get it to display the persons name (user column) in the user table? not sure if i was supposed to change to sum because it didn't work the other way.
$sql = ("SELECT a.id, b.TotalXP, c.TotalLevel
FROM (SELECT DISTINCT id FROM factions_mcmmo_users) a
INNER JOIN (
SELECT user_id, Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy) as TotalXP
FROM factions_mcmmo_experience
GROUP By user_id
) b on b.user_id = a.id
INNER JOIN (
SELECT user_id, Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy) as TotalLevel
FROM factions_mcmmo_skills
GROUP by user_id
) c on c.user_id = a.id
ORDER BY TotalLevel DESC
LIMIT 10;");
EDIT 4
Everything working but when i try to format the totals using "FORMAT(Sum(Columns), 0) on the inner joins, the EXP Total appears to work but the main Total Level is not displaying results that are over 1,000 and it breaks the leaderboard positioning, it should be sorting them on total level but it appears to be random, when u remove the format,0 it goes back to working
I would like it to display commas if the number number is the thousands for example: Total Level: 5,532 and Total EXP 5882,882
See live demo: http://mcbuffalo.com/playground/leaderboards/server/factions-mcmmo.php
Updated Code trying to use Format:
$sql = ("SELECT a.id, a.user, b.TotalXP, c.TotalLevel
FROM (SELECT id, user FROM factions_mcmmo_users) a
INNER JOIN (
SELECT user_id, FORMAT(Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy), 0) as TotalXP
FROM factions_mcmmo_experience
GROUP By user_id
) b on b.user_id = a.id
INNER JOIN (
SELECT user_id, FORMAT(Sum(taming)+Sum(mining)+Sum(woodcutting)+Sum(repair)+Sum(unarmed)+Sum(herbalism)+Sum(excavation)+Sum(archery)+Sum(swords)+Sum(axes)+Sum(acrobatics)+Sum(fishing)+Sum(alchemy), 0) as TotalLevel
FROM factions_mcmmo_skills
GROUP by user_id
) c on c.user_id = a.id
ORDER BY TotalLevel DESC;");
EDIT 5
Changed number with PHP, everything works
Original Images
you could use an couple of inner join
$sql = ("SELECT a.id, a.name, b.TotalXP, c.TotalLevel
FROM (SELECT DISTINCT id, name FROM factions_mcmmo_users) a
INNER JOIN (
SELECT user_id, COUNT(*) as TotalXP
FROM factions_mcmmo_experience
GROUP By user_id
) b on b.user_id = a.id
INNER JOIN (
SELECT user_id, COUNT(*) as TotalLevel
FROM factions_mcmmo_skills
GROUP by user_id
) c on c.user_id = a.id
LIMIT 10

Left Join to get previous record sql

So I am working on a system to manage best before checks in stores and when you're on a overview page of a check you see the following table
Productgroup -> Productname -> Barcode -> Checked -> Checked Time -> New best before -> Old best before
I managed to gather all the data but Old best before using this query:
SELECT `thtchecksproducts`.*, productName, productGroup, productBarcode FROM `thtchecksproducts`
LEFT JOIN `products` ON thtchecksproducts.productID = products.productID
WHERE `checkID`=:checkID ORDER BY checked DESC, productGroup ASC, productName ASC
now I need it to do another left join with the FROM table, thtchecksproducts. It needs to join on productID just like the last one but only with the last record that matches this query:
SELECT productID, max(id) FROM thtchecksproducts WHERE checkID IN (SELECT checkID FROM thtchecks WHERE userID=:userID AND closed=1 AND checkID IS NOT :checkID)
I came up with this:
SELECT s1.*, productName, productGroup, productBarcode FROM `thtchecksproducts` s1
LEFT JOIN `products` ON thtchecksproducts.productID = products.productID
LEFT JOIN thtchecksproducts s2 ON s1.productID = s2.productID
AND s1.id = (SELECT productID, max(id) FROM thtchecksproducts
WHERE checkID IN (SELECT checkID FROM thtchecks WHERE userID=:userID AND closed=1 AND checkID IS NOT :checkID) AND productID = s1.productID)
WHERE `checkID`=:checkID ORDER BY checked DESC, productGroup ASC, productName ASC
Anyone who could help me getting this to work?
Steffan:
You need to provide columns of all tables in your problem and business logic.
What rule describes "Old best before date"? Is the "New Best Before date" always greater than sysdate? In addition, is the query to determine the "Old best before date" always firing before a "New best before date" has been committed?
CK.

how to search product from 6 tables in MySQL database?

SELECT FROM solarbricklight, solarcharger, solarlantern, solarled, solarlightfan, solarlightingkits
WHERE ="productid AND productname"
ORDER BY productid
Your question is not very clear.
But still let me try. Assuming that theres productid and productname in each of your tables (for purpose of an example I am assuming that there are three tables t1, t2 and t3). Heres what you will do...
$query = "(SELECT productid, productname, 't1' as type FROM t1 WHERE productid = 1 OR productname LIKE '%" . $keyword ."%') UNION (SELECT productid, productname, 't2' as type FROM t2 WHERE productid = 1 OR productname LIKE '%" . $keyword ."%') UNION (SELECT productid, productname, 't3' as type FROM t3 WHERE productid = 1 OR productname LIKE '%" . $keyword ."%')";
mysql_query($query);
So, you are getting result from all of the three tables, and you can identify which row came from which table by looking at its type value.
Looks like you should thing about a database design like this:
TABLE PRODUCTS
product_id (int autoincrament)
product_name (varchar(50))
Then you SQL can be like :
SELECT product_id, product_name FROM products WHERE product_name LIKE "%search_string%"
ORDER BY product_id ASC
If you want to search from six tables independently, then use union all:
SELECT
FROM solarbricklight
WHERE ="productid AND productname"
UNION ALL
SELECT
FROM solarcharger
WHERE ="productid AND productname"
UNION ALL
SELECT
FROM solarlantern
WHERE ="productid AND productname"
UNION ALL
SELECT solarled
FROM olarlightfan
WHERE ="productid AND productname"
UNION ALL
SELECT
FROM solarlightingkits
WHERE ="productid AND productname"
ORDER BY productid;
You need to be sure the columns in the select clause are all compatible (and all have the same number). The final ORDER BY refers to the results of the entire query.
Here are some tutorials on database designs - read this, then start designing your database :)
http://www.ntu.edu.sg/home/ehchua/programming/sql/Relational_Database_Design.html
http://www.datanamic.com/support/lt-dez005-introduction-db-modeling.html
A beginner's guide to SQL database design

How do I combine select statements for all values in a many-to-many table

I'm working on an existing product database trying to clean things up. I have the following tables:
Tables
<products> id, title
<keywords> id, title
<product_has_keyword> product_id, keyword_id
When I want to generate a list of products I use the code:
SELECT * FROM products;
And then for each product:
SELECT k.title FROM keywords k, product_has_keyword phk WHERE k.id = phk.keyword_id AND phk.id = ?
How would I change this code into a single SELECT that perhaps returns products in addition to the keywords (separated by spaces) like "id, title, keywords"?
Such as (1, "hammer", "tool home hand"), (2, "blender", "kitchen home"), etc...
You can use the GROUP_CONCAT but be aware of that it has the limit of character to group
SELECT p.id, p.title ,GROUP_CONCAT(k.title SEPARATOR ' ') `keywords`
FROM
products p
LEFT JOIN product_has_keyword phk ON(p.id = phk.product_id)
LEFT JOIN keywords k ON (k.id = phk.keyword_id )
WHERE phk.id = ?
GROUP BY p.id

Confused on how to combine results from two queries

Query 1:
SELECT count(id) as conversions, SUM(user_payout) as amount, geoip.country_name, geoip.country_code
FROM conversions
LEFT JOIN geoip ON conversions.end_ip BETWEEN geoip.start_long AND geoip.end_long
WHERE user_id = 1
AND type != ''
AND status = 1
AND month(created_at) = month(now())
GROUP BY country_name
ORDER BY country_name ASC
Results:
Query 2:
SELECT count(id) as clicks, geoip.country_name, geoip.country_code
FROM clicks
LEFT JOIN geoip on clicks.ip BETWEEN geoip.start_long AND geoip.end_long
WHERE user_id = 1
AND month(created_at) = month(now())
GROUP BY country_name
ORDER BY country_name ASC
Results:
I'd like to combine the two so for each country, it shows clicks, conversions, country_name and country_code.
Can't figure out how to do this.
Thanks!
You can combine them using subqueries and left outer join:
select clicks.country_code, clicks.country_name,
coalesce(clicks.clicks, 0) as clicks,
coalesce(conversions.conversions, 0) as conversions
from (<subquery 2>) clicks left outer join
(<subquery 1>) conversions
on clicks.country_code = conversions.country_code;
This assumes that all countries have at least one click.
EDIT:
If the list of countries is in geo_ip, you can do:
select gi.country_code, gi.country_name, clicks.clicks, conversions.conversions
from (select distinct country_code, country_name
from geo_ip
) gi left outer join
(<subquery 2>) clicks
on clicks.country_code = gi.country_code left outer join
(<subquery 1>) conversions
on conversions.country_code = gi.country_code;
Left Join clicks on the first query to geoip.
Or you could use a union but you would have go get each result to only show clicks, conversions, country_name and country_code by only selecting those in the select statement.

Categories