Basic SQL query design issue - php

I'm trying to create a query that would basically be the equivelant of this (does not work).
SELECT * FROM `categories` AS C AND
SELECT * FROM `items` AS I AND
SELECT COUNT(I.id) AS items AND
SELECT SUM(I.price) AS price;
I am not using SQLServer, and I'm using PDO through PHP for database connectivity.
Here's the tables.
Category
+----+------------+
| id | Category |
+----+------------+
| 1 | First_Cat |
| 2 | Second_Cat |
+----+------------+
items
+----+----------+------+-------+
| id | category | name | price |
+----+----------+------+-------+
| 1 | 1 | Foo | 1.99 |
| 2 | 1 | Bar | 2.00 |
| 3 | 2 | ooF | 0.99 |
| 4 | 2 | raB | 1.99 |
+----+----------+------+-------+
Based on these tables I would be expecting these query results:
+----+------------+-------+-------+--+
| id | category | items | price | |
+----+------------+-------+-------+--+
| 1 | First_Cat | 2 | 3.99 | |
| 2 | Second_Cat | 2 | 2.98 | |
+----+------------+-------+-------+--+
Any help?

The query that you have posted in the comment you are not joining the category table and the item table. That makes me think that you could do something like this?:
SELECT
categories.id,
categories.Category,
COUNT(*) AS items,
SUM(items.price) as price
FROM
`categories`
JOIN items
ON categories.id = items.category
GROUP BY
categories.id,
categories.Category

Related

Executing Different mysql selects based on a field

i have a series of tables for an asset checkout system. there are 2 types of assets.. Stocks and Assets. they all have barcodess stored in a separate table. this is how my tables look
Checkouts table: (sipe_check_out)
+----+--------+----------+----------+-----+---------------------+----------+------+----------+
| id | job_id | stock_id | asset_id | qty | out_time | user_out | note | depot_id |
+----+--------+----------+----------+-----+---------------------+----------+------+----------+
| 1 | 1625 | 0 | 1026 | 1 | 0000-00-00 00:00:00 | 1288 | | 1 |
+----+--------+----------+----------+-----+---------------------+----------+------+----------+
| 2 | 1625 | 8 | 0 | 10 | 0000-00-00 00:00:00 | 1288 | | 0 |
+----+--------+----------+----------+-----+---------------------+----------+------+----------+
barcodes table: (sipe_barcodes)
+----+----------+----------+---------+
| id | stock_id | asset_id | barcode |
+----+----------+----------+---------+
| 1 | 0 | 1026 | AR2221 |
+----+----------+----------+---------+
| 2 | 8 | 0 | MAR0001 |
+----+----------+----------+---------+
Stock Table: (sipe_stock)
+-----+------------+-----------+--------+----------+---------------------+------+--------------+------+-------------+
| id | title | alt_title | status | category | last_updated | memo | replace_cost | flag | description |
+-----+------------+-----------+--------+----------+---------------------+------+--------------+------+-------------+
| 8 | Cable XLR | Cable XLR | 2 | 10 | 2019-01-03 20:45:40 | | 750 | 0 | |
+-----+------------+-----------+--------+----------+---------------------+------+--------------+------+-------------+
| 237 | Fresnel 1K | | 0 | 43 | 2019-01-02 19:08:45 | | 12000 | 0 | |
+-----+------------+-----------+--------+----------+---------------------+------+--------------+------+-------------+
Asset Table: (sipe_stock_asset)
+------+----------+-----+--------+--------+---------------------+------+---------------+-------------+-------+
| id | stock_id | qty | serial | status | status_change | memo | purchase_date | retire_date | depot |
+------+----------+-----+--------+--------+---------------------+------+---------------+-------------+-------+
| 1026 | 237 | 1 | | 0 | 2019-01-02 19:09:00 | NULL | NULL | NULL | 1 |
+------+----------+-----+--------+--------+---------------------+------+---------------+-------------+-------+
i need a list of all items checked out to a specific job_id. these items are sotred in the chekout table. but for display purpose i need to get the items barcode (stored in the barcodes table) , items title (stored in the stock table), and qty (stored in the checkout table)
this is my problem. the select query is different for a stock item and for an asset item.
if it is a stock item one needs to get the stock id from the checkout table then get the title from the stock table and the qty from the checkout table.
this is my working query to get stock items
SELECT
sipe_barcodes.barcode,
sipe_stock.title,
sipe_check_out.qty,
sipe_check_out.out_time
FROM
sipe_barcodes
INNER JOIN sipe_stock ON (sipe_barcodes.stock_id = sipe_stock.id)
INNER JOIN sipe_check_out ON (sipe_stock.id = sipe_check_out.stock_id)
WHERE
sipe_check_out.job_id = 1625
this returns the following
+---------+-----------+-----+---------------------+
| barcode | title | qty | out_time |
+---------+-----------+-----+---------------------+
| MAR0001 | Cable XLR | 10 | 0000-00-00 00:00:00 |
+---------+-----------+-----+---------------------+
If the item is a a stock. we get the asset_id from the checkout. but then we need to get the stock_id from the checkout table so we can get the stock title from the stock table. the qty from the checkout table and the barcode from the barcode table
this is my working query to get asset items
SELECT
sipe_barcodes.barcode,
sipe_stock.title,
sipe_check_out.qty,
sipe_check_out.out_time
FROM sipe_check_out
INNER JOIN sipe_stock_asset ON (sipe_check_out.asset_id = sipe_stock_asset.id)
INNER JOIN sipe_stock ON (sipe_stock_asset.stock_id = sipe_stock.id)
LEFT JOIN sipe_barcodes ON (sipe_check_out.asset_id = sipe_barcodes.asset_id)
WHERE sipe_check_out.job_id = 1625
this retuns this
+---------+------------+-----+---------------------+
| barcode | title | qty | out_time |
+---------+------------+-----+---------------------+
| AR2221 | Fresnel 1K | 1 | 0000-00-00 00:00:00 |
+---------+------------+-----+---------------------+
The Problem
how do i structure a single mysql query that can select all items checked out no matter if they are assets or stocks producing the following output
+---------+------------+-----+---------------------+
| barcode | title | qty | out_time |
+---------+------------+-----+---------------------+
| AR2221 | Fresnel 1K | 1 | 0000-00-00 00:00:00 |
+---------+------------+-----+---------------------+
| MAR0001 | Cable XLR | 10 | 0000-00-00 00:00:00 |
+---------+------------+-----+---------------------+
your help is much Appreciated
Thanks
You may use UNION with your provided select statements
SELECT
sipe_barcodes.barcode,
sipe_stock.title,
sipe_check_out.qty,
sipe_check_out.out_time
FROM
sipe_barcodes
INNER JOIN
sipe_stock ON (sipe_barcodes.stock_id = sipe_stock.id)
INNER JOIN
sipe_check_out ON (sipe_stock.id = sipe_check_out.stock_id)
WHERE
sipe_check_out.job_id = 1625
UNION ALL
SELECT
sipe_barcodes.barcode,
sipe_stock.title,
sipe_check_out.qty,
sipe_check_out.out_time
FROM
sipe_check_out
INNER JOIN
sipe_stock_asset ON (sipe_check_out.asset_id = sipe_stock_asset.id)
INNER JOIN
sipe_stock ON (sipe_stock_asset.stock_id = sipe_stock.id)
LEFT JOIN
sipe_barcodes ON (sipe_check_out.asset_id = sipe_barcodes.asset_id)
WHERE
sipe_check_out.job_id = 1625

How can I create this mysql "SELECT" query?

I have two mysql tables named 'categories' and 'products'.
These are data of that tables.
mysql> select * from categories;
+-------------+--------+----------------------+-------------+
| category_id | parent | name | description |
+-------------+--------+----------------------+-------------+
| 1 | NULL | Products | NULL |
| 2 | 1 | Computers | NULL |
| 3 | 2 | Laptops | NULL |
| 4 | 2 | Desktop Computers | NULL |
| 5 | 2 | Tab PCs | NULL |
| 6 | 2 | CRT Monitors | NULL |
| 7 | 2 | LCD Monitors | NULL |
| 8 | 2 | LED Monitors | NULL |
| 9 | 1 | Mobile Phones | NULL |
| 10 | 9 | LG Phone | NULL |
| 11 | 9 | Anroid Phone | NULL |
| 12 | 9 | Windows Mobile | NULL |
| 13 | 9 | iPad | NULL |
| 14 | 9 | Samsung Galaxy | NULL |
| 15 | 1 | Digital Cameras | NULL |
| 16 | 1 | Printers and Toners | NULL |
| 22 | 1 | Computer Accessaries | NULL |
| 23 | 22 | USB Cables | NULL |
| 24 | 22 | Network Cables | NULL |
+-------------+--------+----------------------+-------------+
24 rows in set (0.00 sec)
mysql> select product_id, category_id from products;
+------------+-------------+
| product_id | category_id |
+------------+-------------+
| 1 | 24 |
| 2 | 6 |
| 3 | 6 |
| 4 | 6 |
+------------+-------------+
4 rows in set (0.05 sec)
Now I need to create a select query to get products to each category. I have already have category_id.
This is how I tried it:
SELECT * FROM products
WHERE category_id = 6
ORDER BY added_date DESC
My question is when I creating this select query I need all the products if one category have its subcategories. That mean, if category_id is 2, then I need to get all the products including its sub categories.
Can anybody tell me how I create this select query?
Thank you.
SELECT *
FROM products
WHERE category_id = 2 OR
category_id IN (SELECT category_id
FROM categories
WHERE parent = 2)
ORDER BY added_date DESC
try this.
select a.*,b.* from categories a inner join products b on a.category_id = b.category_id where a.category_id='$Category_id' or a.parent_id='$category_id'
You can do it using a sub-query to get category_id values whose parent is 2:
SELECT *
FROM products
WHERE category_id = 2 OR
category_id IN (SELECT category_id
FROM categories
WHERE parent = 2)
ORDER BY added_date DESC
All of the above answers will work but only for one level deep of categories. If you need sub-sub-categories then I'd suggest using something called MPTT. This will require 2 new fields in your categories database table though (typically called left and right).

MYSQL OR two values on one column

I have 2 tables.
Table 1: tA
+----+--------------------+
| id | url |
+----+--------------------+
| 1 | hxxp://www.aaa.com |
| 2 | hxxp://www.bbb.com |
+----+--------------------+
Table 2: tB
+----+-------+--------+----------+
|id | tA_id | cat_id | cat_name |
+----+-------+--------+----------+
| 1 | 1 | 1 | Mobile |
| 2 | 1 | 2 | Other |
| 3 | 2 | 2 | Other |
+----+-------+--------+----------+
Expected Output
+----+-------+--------+----------+
| id | tA_id | cat_id | cat_name |
+----+-------+--------+----------+
| 1 | 1 | 1 | Mobile |
| 3 | 2 | 2 | Other |
+----+-------+--------+----------+
mysql code:
select *
from tA
inner tB
on tA.id = tB.tA_id
where tB.cat_id = 1
or tB.cat_id = 2
Group By tA_id
result from my mysql code:
+----+-------+--------+----------+
| id | tA_id | cat_id | cat_name |
+----+-------+--------+----------+
| 1 | 1 | 2 | Other |
| 3 | 2 | 2 | Other |
+----+-------+--------+----------+
How do I do?
Remove your group by tA_id because it is grouping cat_name Mobile and Other together.
If you need to keep it use ORDER BY tB.cat_id ASC which i believe will show the cat_id 1 and 2 like you need it
There is an error in query... JOIN is missing...
QUERY
SELECT *
FROM tA
INNER JOIN tB
ON tA.id = tB.tA_id
WHERE tB.cat_id = 1
OR tB.cat_id = 2
GROUP BY tA_id
This is fetching expected results
+----+---------------------+-----+--------+--------+----------+
| id | url | id | tA_id | cat_id | cat_name |
+----+---------------------+-----+--------+--------+----------+
| 1 | hxxp://www.aaa.com | 1 | 1 | 1 | mobile |
| 2 | hxxp://www.bbb.com | 3 | 2 | 2 | other |
+----+---------------------+-----+--------+--------+----------+
Try this :-
select *
from tA
inner join tB
on tA.id = tB.tA_id
where tB.cat_id = 1
or tB.cat_id = 2
group by tb.cat_name;
Hope it will help you.

SQL query statement table joins

I have a problem with a SQL query and the resultset being returned not being what I expected.
I have these three tables that I am trying to relate.
events_detail
__________________
| ID | start_date |
| 1 | 2012-08-09 |
| 2 | 2013-02-13 |
| 3 | 2012-12-12 |
| 4 | 2013-01-21 |
| 5 | 2012-12-25 |
-------------------
where ID is the primary key
events_category_relationship
__________________________
| ID | event_id | cat_id |
| 1 | 1 | 1 |
| 2 | 2 | 4 |
| 3 | 3 | 2 |
| 4 | 4 | 2 |
| 5 | 5 | 3 |
--------------------------
where ID is primary key
events_category_detail
__________________________________
| ID | name | description |
| 1 | Europe | Kings and castles! |
| 2 | USA | Freedoms |
| 3 | China | Made in China |
| 4 | UK | Big Brother |
------------------------------------
where ID is primary key
What I need to do is grab only 1 event from each category and sorted by date of earliest appearance. So what I should expect in my result is the following
Result Set
________________________________________________________________
| e_id | start_date | c_id | category_name | category_desc |
| 1 | 2012-08-09 | 1 | Europe | Kings and castles! |
| 3 | 2012-12-12 | 2 | USA | Freedoms |
| 5 | 2012-12-25 | 3 | China | Made in China |
| 2 | 2013-02-13 | 4 | UK | Big Brother |
-----------------------------------------------------------------
My SQL query that I tried looks like this
SELECT e.id, e.start_date, c.category_name, c.category_desc
FROM events_detail e
JOIN events_category_relationship r ON r.event_id = e.id
JOIN events_category_detail c ON c.id = r.cat_id
ORDER BY date(e.start_date)
This just joins the 3 tables and returns the result in order by date. What I am stuck on is making it so that only one of each category is displayed like the desired result set above. I have tried using DISTINCT c.category_name and GROUP BY c.category_name, but none of them works.
Any help or advice will be greatly appreciated.
You will want to use a subquery to get the min(start_date) for each name and description. You will then use this result to join back to your events_details table to get the id associated with the data in the subquery:
SELECT e.id,
d.start_date,
d.name,
d.description
FROM events_detail e
INNER JOIN
(
select min(e.start_date) Start_date,
c.name,
c.description
from events_detail e
INNER JOIN events_category_relationship r
ON r.event_id = e.id
INNER JOIN events_category_detail c
ON c.id = r.cat_id
group by c.name, c.description
) d
on e.start_date = d.Start_date
ORDER BY date(e.start_date)
See SQL Fiddle with Demo

Count the frequency of votes in MySQL

I am making a website where users can vote on which category a page is. They can vote that the page is in category a, b, c, or d.
I need to find the most commonly occurring category in the MySQL row out of all the votes.
Each time a user submits their vote, it submits the "category" that they voted for, and the "page_id".
I have this so far:
SELECT page_id, category
FROM categories
GROUP BY page_id
I cannot use a COUNT(*) WHERE category = 'a' then repeat it for each category because there is many more categories in the actual project.
If your table looks something like this:
SELECT * from categories;
+---------+----------+
| page_id | category |
+---------+----------+
| 1 | a |
| 1 | b |
| 1 | a |
| 1 | c |
| 1 | a |
| 1 | b |
| 1 | a |
| 2 | d |
| 2 | d |
| 2 | c |
| 2 | d |
| 3 | a |
| 3 | b |
| 3 | c |
| 4 | c |
| 4 | d |
| 4 | c |
+---------+----------+
17 rows in set (0.00 sec)
Then you may want to try this query:
SELECT c1.page_id, MAX(freq.total),
(
SELECT c2.category
FROM categories c2
WHERE c2.page_id = c1.page_id
GROUP BY c2.category
HAVING COUNT(*) = MAX(freq.total)
LIMIT 1
) AS category
FROM categories c1
JOIN (
SELECT page_id, category, count(*) total
FROM categories
GROUP BY page_id, category
) freq ON (freq.page_id = c1.page_id)
GROUP BY c1.page_id;
Which returns this:
+---------+-----------------+----------+
| page_id | MAX(freq.total) | category |
+---------+-----------------+----------+
| 1 | 4 | a |
| 2 | 3 | d |
| 3 | 1 | a |
| 4 | 2 | c |
+---------+-----------------+----------+
4 rows in set (0.00 sec)
Compare the results with the actual frequency distribution:
SELECT page_id, category, COUNT(*) FROM categories GROUP BY page_id, category;
+---------+----------+----------+
| page_id | category | COUNT(*) |
+---------+----------+----------+
| 1 | a | 4 |
| 1 | b | 2 |
| 1 | c | 1 |
| 2 | c | 1 |
| 2 | d | 3 |
| 3 | a | 1 |
| 3 | b | 1 |
| 3 | c | 1 |
| 4 | c | 2 |
| 4 | d | 1 |
+---------+----------+----------+
10 rows in set (0.00 sec)
Note that for page_id = 3, there is no leading frequency, in which case this query makes no guarantee on which category will be chosen in such a case.
something like
SELECT category, page_id, count(vote_id)
FROM categories
WHERE category in ('a', 'b', 'c', 'd')
GROUP BY category, page_id
ORDER BY count(vote_id) DESC
LIMIT 1
should do the trick. I assume here the votes are individually stored in a separate row per vote.
It only looks in the cqtegory you're interested in, sorts with the most votes first and only returns the first one.

Categories