mysql query with subquery loop? - mysql

I have a query
SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid = 'broker'
AND
cancelled is null
GROUP BY product
WITH ROLLUP
Is it possible to query a table to get a brokers id and then for each broker run the query above written as 1 query?
Almost like:
SELECT brid FROM membership
THEN
SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid = membership.brid
AND
cancelled is null
GROUP BY product
WITH ROLLUP
THEN
SELECT NEXT brid
Is this possible? i know how to do it in PHP but i would prefer 1 query that can create an array rather than tons of queries for each.
Thanks
Adam.

Sure, you can GROUP BY both the 'brid' field and the 'product' field. As noted below, WITH ROLLUP will cause it to sort by 'brid' and then by 'product':
SELECT
brid,
count(product) as amount,
product,
sum(price) AS price
FROM `products`
WHERE
brid IN (SELECT brid FROM membership)
AND
cancelled is null
GROUP BY brid, product
WITH ROLLUP

SELECT
count(product) as amount,
product,
sum(price) AS price
FROM `products`
INNER JOIN membership on membership.brid = products.brid
WHERE
cancelled is null
GROUP BY product
WITH ROLLUP

As far as I can understand from your example, all you need is inner join between membership and products on brid
Take the following example:
products table:
CREATE TABLE `test` (
`price` int(11) DEFAULT NULL,
`product` varchar(20) DEFAULT NULL,
`brid` varchar(20) DEFAULT NULL,
`cancelled` varchar(20) DEFAULT NULL
)
membership table:
CREATE TABLE `membership` (
`brid` varchar(20) DEFAULT NULL
)
And following is my query as you required:
SELECT
t.brid, count(t.product) as amount,
t.product,
sum(t.price) AS price
FROM products t, membership m
WHERE
t.brid = m.`brid`
AND
cancelled is null
GROUP BY product
Hope that helps!

Related

Why is the `ORDER BY RAND()` statement not working in my query?

I have a database where I save information about my products. I use a query for getting those products from my table. The query looks like this:
SELECT * FROM products WHERE stock > 0 ORDER BY RAND();
This query returns all the products that have stock > 0 in a random order, and it works ok. However, now I want to get those products with stock = 0, but I want them to appear at the end of the query (also in a random way but always after products that have stock > 0). So I tried a new query which looks like this:
(SELECT * FROM products WHERE stock > 0 ORDER BY RAND())
UNION
(SELECT * FROM products WHERE stock = 0 ORDER BY RAND());
...this query returns the zero-stock products at the end, but it seems to ignore the ORDER BY RAND() statement and I always get them in the same order. So my question is: how can I get a random response from the query mantaining the condition of zero-stock products at the end?
You don't need UNION:
SELECT *
FROM products
ORDER BY stock = 0, RAND();
The condition stock = 0 in the ORDER BY clause makes sure that the zero-stock products are placed last and the 2nd level of sorting with RAND() randomizes the rows in each of the 2 groups.
SQL Fiddle
Use a case statement to create a field to order by
e.g.
CREATE TABLE IF NOT EXISTS `products` (
`id` int(6) unsigned NOT NULL,
`stock` int(3) unsigned NOT NULL,
`product` varchar(200) NOT NULL,
PRIMARY KEY (`id`,`product`)
) DEFAULT CHARSET=utf8;
INSERT INTO `products` (`id`, `stock`, `product`) VALUES
('1', '10', 'Timber'),
('2', '12', 'Nails'),
('1', '0', 'Glue'),
('1', '0', 'Left handed wrench.');
And run
SELECT stock, product, case when stock > 0 then 1 else 2 end as SetOrder
FROM products
ORDER BY SetOrder, RAND()
Gets you
stock product SetOrder
10 Timber 1
12 Nails 1
0 Glue 2
0 Left handed wrench. 2
SQL Fiddle

Create an MySQL query

I have a table like this
http://sqlfiddle.com/#!9/052381/1
I need to create a request that will find VIN codes that meet the following conditions:
VIN starts with XTA%
I have registration history: date_reg_last values: 1306440000,1506715200,1555963200. You need to select only those VIN codes that have exactly these values. If there are more or less records - VIN does not match
I have an owner_type that matches the values ​​1306440000,1506715200,1555963200: 2, 2, 2. Ie. for record 1306440000 owner_type must be 2, for record 1506715200 also 2, etc. The type can be different for each entry.
Similarly to the third point, I have regions: УЛЬЯНОВСК Г.,УЛЬЯНОВСК Г.,С РУНГА
I have a year, it should be in all records.
I tried making a request like this
SELECT *
FROM `ac_gibdd_shortinfo`
WHERE `vin` LIKE 'XTA%'
AND `model` LIKE '%1119%'
AND `date_reg_first` IN (0,1506715200,1555963200)
AND `date_reg_last` IN (1306440000,1506715200,1555963200)
AND `year` LIKE '2011'
AND `location` IN ('УЛЬЯНОВСК Г.','С РУНГА')
But it finds records that have a different number of registration records. There is only one thought: get all the matching records and then filter them by number with an additional request.
Test this:
SELECT *
FROM `ac_gibdd_shortinfo` t0
WHERE `vin` LIKE 'XTA%'
AND `model` LIKE '%1119%'
AND `date_reg_first` IN (0,1506715200,1555963200)
AND `date_reg_last` IN (1306440000,1506715200,1555963200)
AND `year` LIKE '2011'
AND `location` IN ('УЛЬЯНОВСК Г.','С РУНГА')
AND NOT EXISTS ( SELECT NULL
FROM ac_gibdd_shortinfo t1
WHERE t0.vin = t1.vin
AND t1.date_reg_first NOT IN (0,1506715200,1555963200) )
AND NOT EXISTS ( SELECT NULL
FROM ac_gibdd_shortinfo t2
WHERE t0.vin = t2.vin
AND t2.date_reg_last NOT IN (1306440000,1506715200,1555963200) )
AND NOT EXISTS ( SELECT NULL
FROM ac_gibdd_shortinfo t3
WHERE t0.vin = t3.vin
AND t3.location NOT IN ('УЛЬЯНОВСК Г.','С РУНГА') )
PS. According indices will improve.
and have count (1306440000,1506715200,1555963200) - 3 records in total by VIN – blood73
SELECT vin, model, date_reg_first, date_reg_last, `year`, location
FROM `ac_gibdd_shortinfo` t0
WHERE `vin` LIKE 'XTA%'
AND `model` LIKE '%1119%'
AND `date_reg_first` IN (0,1506715200,1555963200)
AND `date_reg_last` IN (1306440000,1506715200,1555963200)
AND `year` LIKE '2011'
AND `location` IN ('УЛЬЯНОВСК Г.','С РУНГА')
AND 3 = ( SELECT COUNT(*)
FROM ac_gibdd_shortinfo t1
WHERE t0.vin = t1.vin );

SELECT count mysql

I have a database called Real_Estate_Lab_Project, I have a table call listings, with a column named listing price.
listing_key int PK
listing_status int
listing_type int
date_listed date
date_expires date
date_unlisted date
reason_unlisted int
address varchar(50)
city varchar(30)
state char(2)
zip_code varchar(10)
lot_number varchar(50)
residential_area int
listing_price int
listing_agreement_signed_date date
remark varchar(1000)
I am trying to run
USE Real_Estate_Lab_Project;
SELECT count(*)
as no_of_listings,
avg(price) as avg_listing_price, sum(listings)
as sum_of_listings, min(price)
as min_price, max(price)
as max_price
from Listing
where status = 'Active'
When I run script it is telling me
Error Code: 1146. Table 'real_estate_lab_project.listing' doesn't exist 0.000 sec, but I know it exists as I can see it when I do
SELECT * from listings.
The date expires column does have some that are expired, but some are not.
What am I missing?
it looks you have to replace 'Listing' with listings in your sql
SELECT count(*)
as no_of_listings,
avg(price) as avg_listing_price, sum(listings)
as sum_of_listings, min(price)
as min_price, max(price)
as max_price
from listings
where status = 'Active
'

Wrong data output in SQL request

I have a table named payments
CREATE TABLE payments (
`id` INT AUTO_INCREMENT PRIMARY KEY NOT NULL,
`student_id` INT NOT NULL,
`datetime` DATETIME NOT NULL,
`amount` FLOAT DEFAULT 0,
INDEX `student_id` (`student_id`)
);
It is necessary to create a query that is find all student_id whose sum payment is less than the biggest one. (it can be more than one user with the same biggest amount of payments)
Let assume for instance this is a test data:
== Dumping data for table payments
id-student_id-datetime-amount
|1|4|2015-06-11 00:00:00|2
|2|5|2015-06-01 00:00:00|6
|3|1|2015-06-03 00:00:00|8
|4|2|2015-06-02 00:00:00|9
|5|4|2015-06-09 00:00:00|6
|6|5|2015-06-06 00:00:00|3
|7|2|2015-06-05 00:00:00|6
|8|3|2015-06-09 00:00:00|12
|14|1|2015-06-01 00:00:00|0
|15|1|2015-06-03 00:00:00|7
|16|6|2015-06-02 00:00:00|0
|17|6|2015-06-07 00:00:00|0
|18|6|2015-06-05 00:00:00|0
Next query shows all students with their sum payments
SELECT `student_id`, SUM(amount) as `sumamount`
FROM `payments`
GROUP BY `student_id`
ORDER BY `sumamount` DESC
Here is write output of this query ordered by sumamount
student_id sumamount
1 15
2 15
3 12
5 9
4 8
6 0
BUT the problem is when I try to get the user who paid less than the biggest one it gives me the wrong answer
Here is the query to get the second user:
SELECT `student_id`, SUM(amount) as `sumamount`
FROM `payments`
GROUP BY `student_id`
HAVING `sumamount` < MAX(sumamount)
ORDER BY `sumamount` DESC
Here is the result
student_id sumamount
3 12
4 8
6 0
As we can see student_id = 5 missed and I have no idea why.
You need to calcualate MAX(sumamount) in a subquery, so that MAX is not grouped by student_id.
SELECT `student_id`, SUM(amount) as `sumamount`, maxsum
FROM `payments`
CROSS JOIN (SELECT MAX(sumamount) AS maxsum
FROM (SELECT SUM(amount) AS sumamount
FROM payments
GROUP BY student_id) t1) t2
GROUP BY `student_id`
HAVING `sumamount` < maxsum
ORDER BY `sumamount` DESC
DEMO

Showing Distinct Values with Aggregates

I have a table for recording daily price from different suppliers. My goal is to find the best (low price) supplier.
The table structure is
Table Name: lab1
Columns: ID, Product_ID, Price_date, Price, Supplier
-----------------------------------------------------------------------------------
ID Product_ID Price_date Price Supplier
--------------------------------------------------------------------------------------
1 8 26-10-2014 1300 SP1
2 8 05-10-2014 1600 SP2
3 8 15-10-2014 1300 SP1
4 8 14-12-2014 1200 SP3
------------------------------------------------------------------------------------------
Create Table Structure
CREATE TABLE clickpic_pricecompare.lab1 (
ID int(11) NOT NULL AUTO_INCREMENT,
Product_ID int(11) DEFAULT NULL,
Price_Date date DEFAULT NULL,
Price decimal(19, 2) DEFAULT NULL,
Supplier varchar(255) DEFAULT NULL,
PRIMARY KEY (ID)
)
ENGINE = MYISAM
COMMENT = 'testing-purpose';
INSERT INTO lab1(ID, Product_ID, Price_Date, Price, Supplier) VALUES
(1, 8, '2014-10-26', 1300.00, 'SP1');
INSERT INTO lab1(ID, Product_ID, Price_Date, Price, Supplier) VALUES
(2, 8, '2014-10-05', 1600.00, 'SP2');
INSERT INTO lab1(ID, Product_ID, Price_Date, Price, Supplier) VALUES
(3, 8, '2014-10-15', 1300.00, 'SP1');
INSERT INTO lab1(ID, Product_ID, Price_Date, Price, Supplier) VALUES
(4, 8, '2014-10-14', 1200.00, 'SP3');
I NEED THE RESULT LOOKS LIKE BELOW
--------------------------------------------------------------------------------------
ID Product_ID Month Price Supplier
--------------------------------------------------------------------------------------
4 8 October 1200 SP3
-------------------------------------------------------------------------------------------
Please help...
You can use self join with the product id and minimum amount of price to get the lowest price row per product id
select l.ID,
l.Product_ID,
monthname(l.Price_Date) `Month`,
l.Price,
l.Supplier
from lab1 l
join (select Product_ID,min(Price) Price
from lab1
group by Product_ID) l1
using(Product_ID,Price)
DEMO
select temp2.id,
temp2.Product_ID,
DATENAME(month, temp2.Price_Date) AS MONTH,
temp1.Min_Price,
temp2.Supplier
from
(
select Product_ID, min(Price) as Min_Price
from lab1
group by Product_ID
) as temp1
inner join
lab1 temp2
on temp1.Product_ID = temp1.Product_ID
and temp1.Min_Price = temp2.Min_Price
I think you are looking for:
select l.ID, l.Product_ID, monthname(l.Price_Date) as Month, l.Price, l.Supplier
from lab1 l join
(select Product_ID, year(l.Price_date) as yr, month(l.Price_Date) as mon, min(Price) as Price
from lab1
group by Product_ID, year(l.Price_date), month(l.Price_Date)
) lmin
on l.Product_id = lmin.Product_id and
year(l.Price_Date) = lmin.yr and
month(l.Price_Date) = lmin.mon;
If you want data only for October, then add a where clause:
where l.Price_Date >= '2014-10-01' and l.Price_Date < '2014-11-01'