MySQL SUM With Grouped Date - php

How to get data Price with grouped date ?
SELECT store.date, store.pic, owner.name,
SUM (CASE WHEN [>>GROUPED store.date<<] THEN store.price) AS total_price
FROM store
JOIN owner
ON store.pic = owner.name GROUP BY store.date
and i want to display like this :
+-------------+------+------------+
| date | name | price |
+-------------+------+------------+
| 2016-09-30 | John | 100000.00 |
| 2016-09-29 | Rey | 125000.00 |
+-------------+------+------------+

Try this will may help you,
SELECT store.date, store.pic, owner.name,SUM(store.price) AS total_price
FROM store
JOIN OWNER ON store.pic = owner.name
GROUP BY store.date
i can't understand why you used case statement in your query

Related

How to select only one record of each category?

Products :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 3 | B | Dell | 1 |
--------------------------------------------
| 4 | B | Dell | 1 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
| 6 | C | Dell | 1 |
--------------------------------------------
Hi everyone, i have a table (products) stored in MySql with many records, for now i'm using this query SELECT * FROM products WHERE sold = 0, in results i get :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 2 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
i want to get only one record from each group, so the results will be like :
--------------------------------------------
| ID | Group | Name | Sold |
--------------------------------------------
| 1 | A | Dell | 0 |
--------------------------------------------
| 5 | C | Dell | 0 |
--------------------------------------------
You could easily do this by using a distinct clause and removing the id column. If you want to keep the id column you need to specify how one would chose which id to keep.
select distinct
`group`
, name
, sold
from
products
where
sold = 0;
To keep the row with the smallest id (as your example shows) something along the lines of the example below would work.
select
id
, `group`
, name
, sold
from
products
where
sold = 0
and id = (
select
min(p.id)
from
products p
where
p.`group` = products.`group`
and p.sold = 0
);
First, change your field named Group to something like Group_Name. GROUP is a reserved keyword, and if it is not causing you problems now it probably will later.
Second, you should ask yourself what you are really after. The following query should generate your desired result. It adds an additional condition where the IDs that are returned are the lowest numbered ID in each group.
SELECT * FROM products
WHERE sold = 0
AND ID IN (SELECT MIN(ID) FROM products WHERE sold = 0 GROUP BY Group_Name)
Why do you want that, though? That is not a normal desired end state. You should ask yourself why you care about the ID. It looks like your goal is to figure out which products have not sold anything. In that case, I would recommend this instead:
SELECT DISTINCT Group_Name, Name
FROM products
WHERE sold = 0
ORDER BY Group_Name, Name
I found the solution by using the statement GROUP BY,
SELECT * FROM products WHERE sold = 0 GROUP BY group
in the results now, i get only one record for each group and the minimal id without adding any other statement, and in my real table i am using product_group instead of group because it's a reserved word.
Try this:
SELECT `ID`, `Group`, `Name`, `Sold` FROM products WHERE sold = 0 GROUP BY `Group`;

Display only first of duplicate column values

How to query for erase the view below?
+-------------------+------------+
| Order_id | Weight |
| 20 | 4 |
| 21 | 5 |
| 22 | 2 |
| 22 | 2 |
+-------------------+------------+
To be like this:
+-------------------+------------+
| Order_id | Weight |
| 20 | 4 |
| 21 | 5 |
| 22 | 2 |
| 22 | |
+-------------------+------------+
When displaying results but not entered into the database.
A simple way is:
select DISTINCT order_id, weight from xyz
UNION
select order_id, null from xyz
group by order_id, weight
having count(*) > 1
Order by weight desc;
The 1st select statement will display all the unique values and 2nd one will retrieve only the repeated values.
In your required output table, it seems like you want to display all the non-repeated rows and the 1st column value of repeated rows but not 2nd column value. The above query will allow you to do that.
OK, here is how to do it:
SELECT
Order_id,
Weight,
if(#order_id = Order_id, '', Weight) as no_dup_weight,
#order_id := Order_id as dummy
FROM Table1
ORDER BY Order_id asc;
You basically need to check to see if the previous Order_id is the same as the current, and if they are, output an empty field.
Here is an SQLFiddle demonstrating the solution.
Do you actually need 2 rows for the dupes? Can't you just use the DISTINCT clause as per http://www.mysqltutorial.org/mysql-distinct.aspx
Or is it important to know what has duplicates. In which case you should look into the GROUP BY clause

Unable to fetch the accurate rooms availability in specific date range

Here is my database structure
Table name :set_inventory, and columns are below
inventory_id | room_id | quantity_start_date | quantity_end_date | total_rooms
1 | 2 | 2015-10-10 | 2015-10-12 | 5
2 | 2 | 2015-10-13 | 2015-10-14 | 10
3 | 2 | 2015-10-15 | 2015-10-17 | 0
Another Table
Table name : rooms, amd columns are
room_id | room_type | room_picture | room_description
2 | standard | pic_link | demo description
Description: In inventory table admin able to set the inventory based on multiple date ranges.
My query:
SELECT rooms.room_id, rooms.room_pic1, rooms.room_type, rooms.maximum_adults,
rooms.maximum_children, rooms.room_amenities,set_inventory.room_id,
set_inventory.quantity_start_date, set_inventory.quantity_start_date,
set_inventory.total_rooms
from rooms, set_inventory
WHERE rooms.room_id = set_inventory.room_id
AND quantity_start_date <= '2015-10-11'
AND quantity_end_date > '2015-10-13'
It shows me the inventory only 5, based in above query,
What i am looking for :actually, i am looking for the result,
for example my check_in_date "2015-10-11" and check_out_date is "2015-10-17"
In this i will be able to notify the customer that
"room is only available for 4 days,
Plz help me , thanks
UPDATED
Try this WHERE condition:
WHERE rooms.room_id = set_inventory.room_id AND DATE(quantity_start_date) <= '2015-10-11' AND DATE(quantity_end_date) > '2015-10-13';
So, minding you want to have the amount of days between these to dates, your query should contain somwthing like this:
SELECT ABS(DATEDIFF(a1.start_date, a2.end_date)) FROM (
SELECT quantity_start_date as start_date FROM set_inventory WHERE quantity_start_date <= '2015-10-11' ORDER BY start_date DESC LIMIT 1) a1, (
SELECT quantity_end_date as end_date FROM set_inventory WHERE quantity_end_date > '2015-10-13' ORDER BY end_date ASC LIMIT 1) a2;
If you try it, you'll get 4 in result.

MySQL Multiple Conditions on Group By / Having Clause

I have three tables that are all inter-related with the following structure.
ModuleCategory Table:
+------------------+----------------+------------+
| ModuleCategoryID | ModuleCategory | RequireAll |
+------------------+----------------+------------+
| 90 | Cat A | YES |
| 91 | Cat B | NO |
+------------------+----------------+------------+
ModuleCategorySkill Table:
+------------------+---------+
| ModuleCategoryID | SkillID |
+------------------+---------+
| 90 | 1439 |
| 90 | 3016 |
| 91 | 1440 |
| 91 | 3016 |
+------------------+---------+
EmployeeSkill Table:
+---------+---------+
| EmpName | SkillID |
+---------+---------+
| Emp1 | 1439 |
| Emp1 | 3016 |
| Emp2 | 1440 |
| Emp2 | 3016 |
| Emp3 | 1439 |
| Emp4 | 3016 |
+---------+---------+
Desired Output:
+------------------+-------+
| ModuleCategory | Count |
+------------------+-------+
| Cat A | 1 |
| Cat B | 3 |
+------------------+-------+
I am trying to group by ModuleCategoryID's and get the count of employees which have the skills being tracked.
Normally, I can do the following query to obtain the numbers:
select mc.ModuleCategory, Count(*) as Count from ModuleCategory as mc
join ModuleCategorySkill as mcs on mc.ModuleCategoryID = mcs.ModuleCategoryID join EmployeeSkill as es on es.SkillID= mcs.SkillID
group by mc.ModuleCategoryID
However, I have a column RequireAll in the ModuleCategory table which if it is set to 'YES' should only count employees as 1 only if they have all the skills in the category. If it is set to NO then it can count each row normally and increase the count by the number of rows it groups by.
I can achieve this by writing separate queries for each modulecategoryID and using a having Count() > 1 (which will find me anyone that has all the skills for ModuleCategoryID 90). If there were 3 skills than I would have to change it to Having Count() > 2. If there isn't anyone that has all the skills specified, the count should be 0.
I need a dynamic way of being able to do this since there is a lot of data and writing one query for each ModuleCategoryID isn't the proper approach.
Also, I am using PHP so I can loop through and create a sql string that can help me achieve this. But I know I will run into performance issues on big tables with a lot of skills and modulecategoryID's.
Any guidance on how to achieve this is much appreciated.
You can do it by joining on the total category counts, and then using conditional aggregation:
select modulecategory,
count(case when requireall = 'yes'
then if(s = t, 1, null)
else s
end)
from (
select modulecategory,empname, requireall, count(*) s, min(q.total) t
from employeeskill e
inner join modulecategoryskill mcs
on e.skillid = mcs.skillid
inner join modulecategory mc
on mcs.modulecategoryid = mc.modulecategoryid
inner join (
select modulecategoryid, count(*) total
from modulecategoryskill
group by modulecategoryid
) q
on mc.modulecategoryid = q.modulecategoryid
group by modulecategory, empname
) qq
group by modulecategory;
demo here
This operates under the assumption an employee isn't going to be allocated the same skill twice, if that is something that may happen, this query is alterable to support it, but it seems like a broken scenario to me.
What we have here is an inner query that collates all the information we need (category name, employee name, whether or not all skills are required, how many skills are in the group per employee, and how many there in the group total), with an outer query that uses a conditional count to change how the rows are tallied, based on the value of requireall.

Select distinct and random rows from one table that match a value from another table

This topic has been much discussed but I was unable to find a solution that I can modify and make it work for my case. So maybe a more advanced expert will be able to help out.
I have a table called keywords which contains about 3000 rows with distinct keywords. Against each keyword there is a matching product_id, which are NOT unique, i.e. some of them are repeated. Table looks something like this:
+---------+------------+
| keyword | product_id |
+---------+------------+
| apple1 | 15 |
| apple2 | 15 |
| pear | 205 |
| cherry | 307 |
| melon | 5023 |
+---------+------------+
I have a second table called inventory that contains about 500K of products each with it's own product ID and other product data.
Now I need to get one random product row from inventory table that matches each product_id from keywords table and insert those rows into another table.
Resulting table should be something like this:
+---------+------------+---------+---------+---------+
| keyword | product_id | product | data1 | data2 |
+---------+------------+---------+---------+---------+
| apple1 | 15 | app5 | d1 | d2 |
| apple2 | 15 | app1 | d1 | d2 |
| pear | 205 | pear53 | d1 | d2 |
| cherry | 307 | cher74 | d1 | d2 |
| melon | 5023 | melo2 | d1 | d2 |
+---------+------------+---------+---------+---------+
This is my query at the moment and the problem is how to get a random product from inventory that matches a product_id:
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords LEFT OUTER JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND();
If you want it to only return rows when there is a match between the tables, then you want a regular (i.e. inner) join not a left outer join. You can also add the word distinct.
SELECT DISTINCT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND();
And if you only want 1 row returned, add limit 1 at the end.
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND() LIMIT 1;
Is this what you want?
SELECT *
FROM (
SELECT keywords.keyword, keywords.product_id, inventory.*
FROM keywords JOIN
inventory
ON keywords.product_id = inventory.id
ORDER BY RAND()
) tmp
GROUP BY tmp.keyword;
I also test it at http://sqlfiddle.com/#!2/e559a9/2/0. Just run some times, the result will be randomize.

Categories