I am struggling with a MySQL query which I cant get to work as I want.
In table1 I have co_id, name, code, product, logindate.
in table2 I have pr_id, productname, productno, price.
I want to count and group the PRODUCT from table1, so I can see how many that have picked for example product 1,2,3 etc.
But when I list the result on the page I will need productname, and productno for each id number in the GROUP search. table1.product is joined with table2.pr_id
This is what I have so far, but I think I am missing something with INNER JOIN or similar, right?
SELECT
codes.pickedgift,
products.productno,
products.productname,
COUNT(codes.pickedgift) as num
FROM
codes,
products
GROUP BY codes.pickedgift
ORDER BY codes.pickedgift
you missing the join condition, when you join 2 tables you should link primary key in table1 to its foreign key in another table, so your query can be:
SELECT
codes.pickedgift,
products.productno,
products.productname,
COUNT(codes.pickedgift) as num
FROM
codes INNER JOIN products ON codes.product = products.pr_id
GROUP BY codes.pickedgift
ORDER BY codes.pickedgift
You should use a sub-select for this query.
-- assuming I have your table structure correct.
SELECT p.productno, p.productname, num
FROM (SELECT codes.pickedgift, COUNT(codes.pickedgift) as num
FROM codes
GROUP BY codes.pickedgift) g
JOIN products p ON p.id = g.pickedgift
ORDER BY g.pickedgift
The other thing you have to make sure of is if you're using a group-by, the fields in your select must either be the fields in the group by, or aggregates. MySQL let's you include columns that are not part of the group-by / aggregate, it becomes ambiguous as to which value productno and productname should be represented, which is why I opted for a sub-select instead.
Related
I often have a situation with two tables in MySQL where I need one record for each foreign key. For example:
table post {id, ...}
table comment {id, post_id, ...}
SELECT * FROM comment GROUP BY post_id ORDER BY id ASC
-- Oldest comment for each post
or
table client {id, ...}
table payment {id, client_id, ...}
SELECT * FROM payment GROUP BY client_id ORDER BY id DESC
-- Most recent payment from each client
These queries often fail because the "SELECT list is not in GROUP BY clause" and contains nonaggregated columns.
Failed Solutions
I can usually work around this with a min()/max() but that creates a very slow query with mis-matched results (row with min(id) isn't equal to row with min(textfield))
SELECT min(id), min(textfield), ... FROM table GROUP BY fk_id
Adding all the columns to GROUP BY results in duplicate records (from the fk_id) which defeats the purpose of GROUP BY.
SELECT id, textfield, ... FROM table GROUP BY fk_id, id, textfield
Same idea as #GurV but using a join instead of a correlated subquery. The basic idea here is that the subquery finds, for each post which has comments, the oldest post and its corresponding id in the comments table. We then join back to comments again to restrict to the records we want.
SELECT t1.*
FROM comments t1
INNER JOIN
(
SELECT post_id, MIN(id) AS min_id
FROM comments
GROUP BY post_id
) t2
ON t1.post_id = t2.post_id AND
t1.id = t2.min_id
You can use a correlated query with aggregation to find out the earliest comment for each post:
select *
from comments c1
where id = (
select min(id)
from comments c2
where c1.post_id = c2.post_id
)
Compound index - comments(id, post_id) should be helpful.
If you are querying the whole table with many rows, then it will. This query is more useful and performant if you are querying for a small subset of posts. If you are querying the whole table, then #Tim's answer is better suited I think.
I know how to query to find records with duplicate records based on a field or fields e.g.
Select Customer,Count(*) from Table1 group by Customer,Month having count(*)>1
which would give me a list of all customers who ordered more than once in a given month.
However from that select I'd like to:
Refine the group to show only dupes where the product is DIFFERENT. I know if I wanted to do the same I'd simple add to group by ',Product' but in my case it is Product != Product and I'm not sure how to indicate that in the group
Instead of getting a list of just which Customers ordered more than one product in a given month a list of all those orders. In other words instead of this type of list from the group:
Bob,December
Mary,June
I am trying to return:
Bob,Widget,December
Bob,Pipes,December
Mary,Books,June
Mary,Cars,June
If product field is in the same table, then you can use count with distinct on the product field to get the number of distinct products:
Select Customer, Month, Count(distinct product)
from Table1
group by Customer, Month
having count(distinct product)>1
If you want to know what they ordered, then join it back as a subquery to your main table:
select distinct t1.customer, t1.month, t1.product from table1 t1
inner join
(Select Customer, Month, Count(distinct product)
from Table1
group by Customer, Month
having count(distinct product)>1
) t2 on t1.customer=t2.customer and t1.month=t2.month
The distinct in the outer select depends on your exact needs.
I have a query:
SELECT DISTINCT *
FROM table1 AS s
LEFT OUTER JOIN table2 AS t
ON s.s_id = t.t_id
WHERE (
s.body LIKE '%string%'
OR t.name LIKE '%string%'
)
ORDER BY s.time DESC
but I am still getting duplicate tuples. Why is this?
GROUP BY s.s_id
was the solution.
The result doesn't contain absolutely equal rows here so technically they aren't duplicated
To get rid of duplicates, you need to SELECT DISTINCT or GROUP BY only fields you need non-duplicated and outer join the rest data in subquery on the corresponding key values, taking only 1 (first or last or whatever) row from them.
I have a table, one column of which is VERY dependant on a bunch of other tables
i can't alter the table, and i can't change the name of the parameter that is used
this is my query :
select *,(select sum(itemQuantity*(select itemPrice from Items where
Items.itemID=OrderItems.itemID)) from OrderItems
where OrderItems.orderNumber=Orders.orderNumber) as orderValue,
(select sum(itemQuantity) from OrderItems where OrderItems.orderNumber=Orders.orderNumber)
as orderItemQuantity from Orders WHERE Orders.customerId =1 AND Orders.beenSupplied =1
and this is the result of this query:
as you can see, i have the column "orderValue" twice
the first orderValue is the original column from the Orders table, and the second orderValue is from the "as" clause in the query
how do i merge the two columns and have the output of the query in it, and not the 0 that constantly gets inserted ?
EDIT:
table structures:
Rather than using SELECT *, explicitly list the columns (from your Orders table) that you wish to select.
You can also avoid using (the highly inefficient) correlated subqueries by joining the tables in the outermost query and then grouping each order.
SELECT Orders.orderNumber,
Orders.customerId,
Orders.orderDate,
Orders.beenSupplied,
Orders.purchaseDate,
SUM(OrderItems.itemQuantity * Items.itemPrice) AS orderValue,
SUM(OrderItems.itemQuantity) AS orderItemQuantity
FROM Orders
JOIN OrderItems USING (orderNumber)
JOIN Items USING (itemID)
WHERE Orders.customerId = 1
AND Orders.beenSupplied = 1
GROUP BY Orders.orderNumber
I need help with some basic sql...
here is the problem:
In first table I have
ID (primary key)
data column (varchar)
which contains products, in other I have
ID (primary)
second ID (foreign key) //references to ID from first table
price (decimal 8,2)
What I need is to SUM price from second table that corresponds products from first table. also it should be saved as view.
any help?
JOIN the two tables, with GROUP BY and an aggregate function SUM like this:
CREATE VIEW DataPrices
AS
SELECT
p.id,
p.data,
SUM(t.price)
FROM products p
INNER JOIN secondtable t ON p.ID = t.ForeignKeyToTable1
GROUP BY p.Id, p.data;
select table1.id, table1.data, sum(table2.price) as `total`
from table1 inner join table2
on table1.id = table2.foreignkeyId
group by table1.id, table1.data