SQL Display table information, when condition true in another table? - php

So I have 2 tables that I'm using. A product table that will fill out some product cards using PHP. What I want to do if make an sql statement to only pull information from the product table if the user has failed a red/green or blue/yellow colorblind test that we setup. So if the user has failed a red/green colorblind test, I want to only pull the product information from the products that have a lenstype of red. And the designation of if they have failed the test is marked as a 1.
Looking for an SQL statement to make this happen.
Userreg
id
bluefail
redfail
1
1
0
2
0
1
3
1
0
Product
prodtitle
lenstype
price
1
blue
10
2
red
10
3
red
10

You can use join like this:
select u.*, p.*
from userreg u join
product p
on (p.lenstype = 'blue' and u.bluefail = 1) or
(p.lenstype = 'red' and u.redfail = 1);
Note that if a user fails both, then they will get products for both types.

Related

Mysql join two table and set group in all tables

Hello I have two table in my database, customers and shops.
I want to get all customers and clarify that a customer is a debtor or not.
For this job I want to create a mysql query that get the customers and join the shop table.
I want to set condition for if shops.price_status column = 1 come and sum price value in shops table.
Otherwise the value of those row for price column in shop table equal to 0.
My shop table structure with some example data
id customer_id product_id price price_status
1 81 12 300 1
2 81 12 100 0
3 81 15 200 1
4 90 10 600 0
5 90 15 50 1
6 63 16 10 0
And my customer table (You should know some customers don't shop any product by I want to see them)
id name
63. Eva
64. Nva
81. Ali
82. Bill
90. Mosh
An I want to get this result
Eva. 0. // Because price status = 0
Nva. 0.
Ali. 500 // because have two row that prices status = 1
Bill. 0.
Mosh. 50. // Because have one row with price status = 1
this can do with [MySQL if][1]
SELECT
c.`name`,sum(if(s.price_status=1,s.price,0)) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;
if you accept null value in price you can use
SELECT
c.`name`,sum(s.price_status*s.price) as price
FROM
customer AS c
LEFT JOIN
shops AS s
ON
c.id=s.customer_id
GROUP BY
c.id;

Not getting required result after joining 2 tables

I have a view where i need to get list of all dishes from menu table according to main_menuid for a particular user, But here i need to put some conditions
Currently i am using 3 tables for the entire process (table view for all 3 is given at the end)
1) main_menu
2) menu
3) cart
1) I need to get list of dishes according to main_menuid
so here if i need a list of dishes below MM1, so list of dishes that i should get from menu table is (main_menuid is the id of main_menu table)
id main_menuid dish
1 1 D1
2 1 D2
3 1 D3
code i used to get the above data is
$sql = "select * from menu where main_menuid = '".$mainmenuid."'";
$result = mysqli_query($con, $sql);
if (mysqli_num_rows($result) > 0)
{
while($row = mysqli_fetch_assoc($result))
{
print_r($row);
}
}
2) i will also have a userid with me so now i need to display the above list to a particular user (Let the userid be "1"), but if he already has added any of the above product to cart earlier then it's quanity should also get fetched from cart and for rest of the items(that are not added by him to the cart but is present in the above list) the quantity will be null, so the resulting view should be like this (menuid is the id of menu table)
id main_menuid menuid dish quantity userid
1 1 1 D1 3 1
2 1 1 D2 2 1
3 1 1 D3 0 1
code that i tried for the above result is (but it didn't gave me the desired result)
SELECT menu.main_menuid, menu.dish, cart.userid,
cart.quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
WHERE main_menuid = '".$main_menuid."' and userid = '".$userid."'
Below is a sample view of all the tables that are being used in the above process
main menu
id mainmenu_name
1 MM1
2 MM2
3 MM3
4 MM4
menu
id main_menuid dish
1 1 D1
2 1 D2
3 1 D3
4 2 D4
5 3 D5
6 4 D6
cart
id userid menuid dish main_menuid quantity
1 1 1 D1 1 3
2 1 2 D2 1 2
3 2 1 D1 1 3
can anyone please tell how to achieve the desired result (DBMS: mysql)
move userID to the join as it is eliminating the null values generated from the left join.
SELECT menu.main_menuid, menu.menuid, menu.dish, cart.userid,
cart.quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
and userid = '".$userid."'
WHERE main_menuid = '".$main_menuid."'
However this implies you want some dishes not associated to the user so userID will be NULL in some cases.
Why does this work and not in the where clause? Because the filter is applied BEFORE the join. This allows the null values which would occur as a result of the left join to remain.
You can't get userid from your cart table directly, if the desired menu item is not in cart. So your WHERE clause filters out these records. Try this request:
SELECT menu.main_menuid, menu.menuid, menu.dish, IF(ISNULL(cart.userid), ".$main_menuid.", cart.userid) AS userid,
IF(ISNULL(cart.quantity), 0, cart.quantity) AS quantity
FROM menu
LEFT JOIN cart ON menu.id=cart.menuid
WHERE menu.main_menuid = '".$main_menuid."'
I think the problem is on the LEFT JOIN. You should do this way:
LEFT JOIN cart ON menu.id=cart.menuid and cart.dish = menu.dish
EDIT
When you do this way, the userid column will be null at the last line, to avoid this, on select you should put something like this:
SELECT menu.main_menuid, menu.dish,
COALESCE(cart.quantity, 0), -- will put 0 when null
COALESCE(cart.userid, '".$userid."') as userid -- will put '".$userid."' when null

Exclude result from MySQL query in JOIN

I have multiple tables with orders and deliveries and I want to get only open orders (only those orders that do not have records in delivery table).
So, my tables look like:
Orders table (sh_comenzi):
id partner
1 Partner X
2 Partner Y
3 Partner Z
4 Partner Q
Order lines table (sh_comenzi_pos) where idc is the id of sh_comenzi table
id idc cPos quantity
1 1 1 5
2 1 2 10
3 1 3 20
4 2 1 10
5 2 2 15
6 3 1 10
7 3 2 5
8 3 3 8
9 4 1 15
The deliveries items table is (sh_delivery_items)
id idc cPos
1 1 1
2 1 3
3 2 2
4 3 1
5 3 2
6 3 3
The desired result should give me an output of open orders just like this:
id partner
1 Partner X
2 Partner Y
4 Partner Q
The result doesn't have to keep track o quantities, just on lines level. If one line from orders exists in sh_delivery_items then that line is closed.
I tried something like this:
SELECT DISTINCT sh_comenzi.id, partner FROM sh_comenzi
LEFT JOIN sh_comenzi_pos ON sh_comenzi.id = sh_comenzi_pos.idc
LEFT JOIN sh_delivery_items ON (sh_comenzi_pos.idc = sh_delivery_items.idc AND sh_comenzi_pos.cPos = sh_delivery_items.cPos)
WHERE sh_comenzi.id IS NOT NULL
ORDER BY sh_comenzi.id DESC
Could someone help me?
This is the query you need:
SELECT DISTINCT c.*
FROM sh_comenzi c
INNER JOIN sh_comenzi_pos p
ON c.id = p.idc
LEFT JOIN sh_delivery_items di # 'di' from 'delivery items'
ON p.idc = di.idc AND p.cPos = di.cPos
WHERE di.id IS NULL # keep only not-delivered items
How it works
It combines all the orders (table sh_comenzi) with their line items (table sh_comenzi_pos). The INNER JOIN will leave out the empty orders (if any); if you need them then use LEFT JOIN instead.
Next, each row (order, line item) is combined with the delivery information (table sh_delivery_items) using the pair of columns (idc, cPos). The LEFT JOIN ensures all the rows from the left side table (or result set) appear in the final result set; if a row from the right side table cannot be found to match the row from the left, a row full of NULLs is used instead. This happens for the line items that were not delivered yet (there is no record for them in sh_delivery_items).
Then, the WHERE clause keeps only the rows having NULLs in the di table (sh_delivery_items), i.e. the line items that were not delivered, together with the orders that own them.
Finally, SELECT DISTINCT c.* selects only the columns from the orders table (sh_comenzi) and DISTINCT ensures each order appear only once. Otherwise, each order appears once for each of its line items that was not delivered.
Complete the query yourself with the desired ORDER BY clause.

Count the number of rows in MySQL table with criteria depending on other table

I've got two tables:
content:
id access
1 3
2 5
3 9
viewlevels:
id group
1 [10,12,15]
2 [8,12,11]
3 [9,10,5]
The access field in content is related with the id field in viewlevels.
I select the rows in viewlevels depending on the current user group. So for example, if group is = 10, my query will select rows 1 and 3. If the group is 12, it will select rows 1 and 2, etc. I'm using the following query:
$query="SELECT id FROM #__viewlevels WHERE rules LIKE '%$group%'";
My challenge is to count the number of rows for column id in table content where the access matches with the selected id's from the above query on table viewlevels.
I tried the following code but it is returning the error: undefined variable: nartigos
$query="SELECT count(id) FROM #__content WHERE access IN (SELECT id FROM #__viewlevels WHERE rules LIKE '%$group%')";
if ($stmt = mysqli_prepare($link, $query)) {
/* execute query */
mysqli_stmt_execute($stmt);
/* store result */
mysqli_stmt_store_result($stmt);
$nartigos=mysqli_stmt_num_rows($stmt);
/* close statement */
mysqli_stmt_close($stmt);
};
echo "NÂș de artigos " .$nartigos;
First of all, you really should normalize your data. Consider having a many-to-many join table for viewLevels instead of having all groups in one row. That might look like this:
access_id group_id
1 10
1 12
1 15
2 8
2 11
2 12
3 5
3 9
3 10
That would make your query as simple as
SELECT c.id AS `content_id`, COUNT(v.access_id) AS `content_count`
FROM content AS c INNER JOIN viewLevels AS v
ON c.access_id = v.access_id
WHERE v.group_id = ?
GROUP BY c.id
Here ? is the group id you are querying against.
Without normalization (which again I STRONGLY recommend you do), you would still use a join, but it would look like this:
SELECT c.id AS `content_id`, COUNT(v.access_id) AS `content_count`
FROM content AS c INNER JOIN viewLevels AS v
ON c.access_id = v.access_id
WHERE v.group LIKE '%?%'
GROUP BY c.id
you need to "join" your tables.
the sql command cant query two tables seperately.
when you "join" 2 tables in your sql, think of it as making one virtual/temporary table in the air, of the 2 tables which you can then query.
this is quite a good intro http://www.sitepoint.com/understanding-sql-joins-mysql-database/

Exploding data from mysql using PHP

I have a database table where I am storing all the values from an external xml file. Since my project requirement demands me to deal with this unnormalized data. I need to help to extract data in an appropriate way.
I have two web pages (one for categories) and one for products.My database table looks like this:
**product_id Code Name ProductRange ProductSubRange WebCategory**
1 1002 Lid 30l Crystal;Uni LIDs Household products
2 10433 Casa Basket Silver Casa Casa Hipster BASKET Kitchenware
3 17443 Casa Basket Ice White Casa;Laundry LAUNDRY BASKET Laundry products
4 13443 Garden tub Eden Eden Garden Pots Household products
5 199990 Black Lid 201 Crystal Crystal Lids Household products
The product that belong to more than one productRange is indicated my semicolon(;). For example,above product_id 1 with name "Lid 301" belongs to two Product Ranges "Crystal" and "Uni". Same is for product_id 3. However product 2 belongs to single ProductRange.
MY QUESTIONs:
1) How can I construct a query so that it could return "ProductRange" based on my query_string values of "Webcategory"? For example:
if I get "Household Products" as my WebCategory from query string, it could give me distinct like this:
Household Products
|-Crystal
|-Uni
|-Eden
Laundry Products
|-Casa
|-Laundry
Kitchenware
|-Casa
2) Based on extracted ProductRanges, I want to display products separately in my webpages according to the product range and webcategory. For example, if I choose "Crystal" from above, it could give me Products with product_id "1" and "5" respectively like this:
Household Products|
|-Crystal
|-Lid 301 (product_id=1)
|-Balck Lid 201 (product_id=5)
|-Uni
|-Lid 301 (product_id=1)
|-Eden
|-Garden Tub
Kitchenware|
|-Casa
|-Casa Basket silver
Laundry Products|
|-Casa
|-Casa Basket Ice White
|
|-Laundry
|-Casa Basket Ice White
Can anyone guide me how can I retrieve records from the database and what I will need to do as I am new to programming? I would appreciate if anyone could help me in this regard.
In order to get distinct product ranges based on a give WebCategory input = 'XYZ', you can use the following - don't be intimidated by the numberstable, it's just a helpful table that contains rows each with increasing integer values from 1 ... up to N where N is the maximum number of characters in your ProductRange column. These can be made by hand or using a special insert/select query like the one found here:
http://www.experts-exchange.com/Database/MySQL/A_3573-A-MySQL-Tidbit-Quick-Numbers-Table-Generation.html
SELECT DISTINCT
SUBSTRING(ProductRange FROM number FOR LOCATE(';', ProductRange, number) - number) AS ProductRange
FROM (
SELECT ProductRange, CASE number WHEN 1 THEN 1 ELSE number + 1 END number
FROM (
SELECT mydatabasetable.ProductRange, numberstable.number
FROM mydatabasetable
INNER JOIN numberstable
ON numberstable.number >= 1
AND numberstable.number <= CHAR_LENGTH(mydatabasetable.ProductRange)
WHERE WebCategory = 'XYZ'
) TT
WHERE number = 1 OR (number + 1) <= CHAR_LENGTH(ProductRange)
) TT
WHERE SUBSTRING(ProductRange FROM number FOR 1) = ';'
OR numberstable.number = 1;
In order to retrieve a result set with all values WebCategory, ProductRange and Product for your website you can use the below slightly modified version derived from the above query. So that the results will appear more meaningful at first, I added an ORDER BY clause to keep all same-category, same-product-range products in sequence one after the other. This might or might not be desired as you might prefer to do that in your application/server-script code. In that case you can remove the ORDER BY clause without doing any harm.
SELECT WebCategory,
SUBSTRING(
ProductRange
FROM number
FOR LOCATE(';', ProductRange, number) - number
) AS ProductRange,
Product
FROM (
SELECT WebCategory, ProductRange, Product,
CASE number
WHEN 1 THEN 1
ELSE number + 1
END number
FROM (
SELECT WebCategory, ProductRange, Product, numberstable.number
FROM mydatabasetable
INNER JOIN numberstable
ON numberstable.number >= 1
AND numberstable.number <= CHAR_LENGTH(ProductRange)
) TT
WHERE number = 1 OR (number + 1) <= CHAR_LENGTH(ProductRange)
) TT
WHERE SUBSTRING(ProductRange FROM number FOR 1) = ';'
OR numberstable.number = 1
ORDER BY WebCategory, ProductRange, Product
You are probably going to want to do a GROUP BY clause in your query and maybe an JOIN if the detailed data is in a different table. If I understand you correctly it would look something like this.
SELECT T.WebCategory, T.ProductRange, T2.Product FROM table T
INNER JOIN table2 T2 ON T2.ProductRange = T.ProductRange
WHERE T.WebCategory = 'Household products'
GROUP BY T.WebCategory, T.ProductRange, T2.Product
It is tough to test my query without having a database setup to test against, but something like the above should return what you are looking for. You will of course need to rename your columns based on the actual names in the second table. Overall though, this should get you started if I understood the question correctly.

Categories