sum row content with matching columns - php

Yes yes, I know. The title is stupid and hard to understand.
Question:
There's a DB1 and a DB2.
DB1 has columns called id and price. id is a unique number for each item like 301 and so on. There's only one of each id in this DB.
DB2 contains a column named id and one named price. This DB has the duty of collecting data about each id ( item ) via a php script.
This means multiple rows with the same unique id.
a picture to demonstrate:
What i'm trying to do:
a script that querys an id ( matches the id with another table ) and sums up all the price columns with the same id.
I understand innerjoin
SELECT db1.id, db2.price
FROM db1
INNER JOIN db2
ON db1.id=db2.id;
but I want to sum all db2.price rows before showing. What can I do?

What you want is this:
(I guess you want to show db1.price too (or other fields from db1, otherwise there is no meaning have this join)
SELECT db1.id, db1.price, db2s.price -- rest of db1 fields here
FROM db1
INNER JOIN (select id, sum(price) price from db2 group by id) as db2s
ON db1.id=db2s.id;
SQLFIDDLE

I don't think you need a join for that. It should be enough to just do:
SELECT id, sum(price) as price_sum FROM db2 GROUP BY id
This should give you 2 columns:
id of the price
sum of all prices for given price ID

Related

MySql List all items from table 1 where item conditionally exists in table 2

Table-1 parts is a full parts catalog. Primary index field is PartID (int, auto-increment).
Table-2 inventory is a list of partIDs connected to various distributors. Important fields are DistID and PartID. Primary index field is InvID (int, auto-increment).
In Table-2, there will be a unique entry (InvID) for each part a distributor has, so many duplicate DistID/PartID entries.
Given a particular DistID, I must first get a list of all PartIDs associated with that DistID (inventory Table-2), and then SELECT * FROM parts (Table-1) for all those PartIDs.
The end result set is a list of all part information (T1) for each unique part held by a distributor (T2).
I'd like to do this using a single mysql query.
What you want is to start with a distinct list of the inventory for that distributor. This is our base query (replace the question mark with your actual distributor ID):
SELECT DISTINCT partID FROM inventory WHERE DistID = ?
Then we modify that query to join on the parts table to pull back the part information:
SELECT DISTINCT i.partID, p.* FROM inventory i INNER JOIN parts p ON i.partID = p.partID WHERE i.DistID = ?
thats not a PHP question at all.
Anyway, if I understood your question your should try this:
SELECT parts.* FROM parts WHERE parts.PartID IN (SELECT invetory.PartID FROM invetory WHERE invetory.DistID = 'wanted_DistID');
You should change 'wanted_DistID' for you wanted DistID.
Hope I could help.

mysql select and join on multiple tables

I'm having tables like
product table: product_id | code
group table: id | fk-product_id | id_code
grade table id | fk-product_id | id_grade
person table id | fk-product_id | id_person
my sql query is:
"SELECT *
FROM product
JOIN group ON group.product_id = product_id
JOIN grade ON grade.product_id = product_id
JOIN person ON person.product_id = product_id
WHERE product.code='".$productCode."'");
I get the wright result, but there is too much of rows. I thing that I'm doing overkill.
All product are for sure in the table "product" but it's not necessary that the same "id_product" is in the table "group", "grade" or "person".
In my result are a lot of rows where my result is repeted. I there any way to avoid those duplication?
Is there better way to perform my query?
From your original query, you have listed the column in the group, grade and person table are
'fk-product_id' but your query is showing as just 'product_id'. So, I am implying your real column is just 'product_id' and the 'fk-' was just a reference that it was the foreign key to products table.
Now, that said, the equality comparison is just product_id. Since you are not qualifying it with alias.field, it is probably grabbing everything since each record in group will always have its own product_id = its own product_id.
In addition, you mention that not all tables will have a matching product ID, so you will need LEFT-JOINs for the other tables... Adjust to something like this
SELECT
p.*,
gp.id_code,
gd.id_grade,
per.id_person
FROM
product p
LEFT JOIN group gp
ON p.product_id = gp.product_id
LEFT JOIN grade gd
ON p.product_id = gd.product_id
LEFT JOIN person per
ON p.product_id = per.product_id
WHERE
p.code='".$productCode."'";
But I would head caution for sql-injection as you could get malicious values in your $productCode variable. Make sure you have it properly cleaned and escaped.
#5er, Left-Join says for each record on the left-side (first in this case is the Product Table), I want all records... and oh... by the way... I have the other tables (group, grade and persons). They MAY have a record too that has the same Product_ID value as the product table. If so, grab those pieces too, but don't exclude the original product record.
Now, why your query was failing, and I thought I described it well, but apparently not. You were getting a Cartesian result which means for every one record in the left-table (product), you were getting EVERY record in the RIGHT-side table... So, for a single product, and if you had 20 group, 10 grades and 100 people, you were basically getting 20,000 records.
So your JOIN
JOIN group ON group.product_id = product_id
WOULD have worked, but had less records IF you qualified with the PRODUCT reference
JOIN group ON group.product_id = PRODUCT.product_id
Otherwise, it was just comparing its own product_ID to itself and saying... Yup, these to product IDs match (even though it was the same record), it returned it. The engine can't guess for you which table you meant for the second part of the join, especially when there were a total of 4 tables referenced in the query, and EACH had a "Product_ID" column. So, I strongly suggest that for ALL your queries, qualify ALL fields as alias.field, including those of the select field list. Then, anyone else trying to help you in the future, or even take over where you left-off know where the fields are. Prevent ambiguity in your queries.
Your select does not match the table/column names above it. For example in table product you say you have column id_product, but in select you use product.id instead of product.id_product. That might be totally different column.
Your results are repeating because the JOIN is joining tables, but you are not filtering those cases where one JOIN matches, while the other isn't.
Try this:
SELECT *
FROM product
JOIN group ON group.product_id = product.id
JOIN grade ON grade.product_id = product.id
JOIN person ON person.product_id = product.id
WHERE product.code='".$productCode."'
GROUP BY product.id

Selecting (SKU)s and (QTY)s using php($sql) which (SKU)s are in Table A but not in Table B

I have couple tables in mssql server and the below is table i have.
Table A have QTY, SKU, ItemID - have 50,000 SKU
Table B have QTY, SKU - have 10,000 SKU - these sku are in Table A
(Table A have more data than Table B)
and i want to select (SKU)s and (QTY)s using php($sql) which (SKU)s are in Table A but not in Table B
Thank you so much guys in advance!
You question nearly uses the exact syntax required. Something like this should work.
select sku, qty from tableA where tableA.sku not in (select sku from tableB)

Trying to select all the records from table B that have the same name as most recently added record from table A

I'm using php and MySQL. I have two tables. I want to select all the records from table PARTS that have the same prod_name as the most recently added record in the table PRODUCTS.
Table PRODUCTS:
id (auto increment)
prod_name
Table PARTS:
prod_name
part_name
part_cost
Will this work or should I use some sort of join?
SELECT * FROM parts WHERE prod_name = (SELECT prod_name FROM products ORDER BY id DESC LIMIT 1)
Yes it will work. You can always execute the query in the phpmyadmin or MySql Query Browser to test it.
It may be better to return the inserted id, and select using that id.
SELECT
parts.*
FROM
parts
INNER JOIN
products
ON
products.prod_name = parts.prod_name
WHERE
products.id = (SELECT MAX(id) FROM products)
That should work - but if products has an auto increment id, why are you using the prod_name as the foreign key in the PARTS table?
Such a design buys you extra work if the user ever wants to change the prod_name (you then have to go through and change the prod_name on all the PARTS, unless you don't mind them losing their connection).
Plus it is not space efficient (unless prod_name is always very short).

Compare database value to number of rows in another table

For each item in the first table, there is a 'numberOf' field. The value of this field must have an identical number of rows in a related table. These are like reservation rows so multiple users can book the item at the same time. This syncronisation sometimes goes out and there are more rows than the 'numberOf' field variable, and vice versa.
So I want to display a table that outputs the 'numberOf' from the first table, and the amount of rows that correspond to it from the other table. They are linked by the Item ID. Hope this isn't too confusing. The query is output with a do while loop. Here is the query I have so far anyway:
$querySync = sprintf("SELECT
COUNT(reserve_id), item_id, details, numberOf
FROM
reservations
JOIN
items ON item_id = itemID_reserved
WHERE
itemID_reserved = 1 ");
So at the moment it counts the number of rows in the reservations table. It then joins the items table so I can display the description and numberOf etc. Of course at the moment it only outputs the item with ID 1. But I can't seem to get it to go though each item, check its numberOf, and compare it to the number of rows in reservations table.
The idea is to have it all on one column and at the end of the row print if it is out of sync etc. I then need to rebuild the rows in the reservations table to match the numberOf.
Sorry thats a long one!
SELECT COUNT(reserve_id), item_id, details, numberOf,
COUNT(reserve_id) > numberOf AS overbook
FROM items
LEFT JOIN
reservations
ON itemID_reserved = item_id
GROUP BY
item_id
It might be easier to just directly calculate which items are "out of sync":
select i.item_id
from reservations r JOIN items i on (i.item_id = r.itemID_reserved)
group by i.item_id
having count(r.itemID_reserved) > i.numberOf
I'm making some assumptions there about which tables have which fields, but it should be sufficiently illustrative.

Categories