mysql rows where count(x) > 1 and count(y) > 0 - mysql

I have a sales table containing invoice number, product code, product category, qty, etc.
Using this table how would you go about finding invoices that contain at least one product from say category A AND 1 product from category B ?

Okay, here's what I believe is what you'll want. Happy to see any simpler suggestions if anyone has them:
Select tableA.invoiceNumber
from
(select * from myTable
where productCategory = 'A') tableA
inner join
(select * from myTable
where productCategory = 'B') tableB
on tableA.invoiceNumber = tableB.invoiceNumber
Here's a SQLFiddle:
http://sqlfiddle.com/#!9/03ddd/3
It's basically joining your query onto itself where there's a condition for each table on category.

Try this :
select * from mytable
inner join(
select invoiceNumber
from mytable
where mytable.productcategory = 'A'
) as a using (invoiceNumber)
inner join(
select invoiceNumber
from mytable
where mytable.productcategory = 'B') as b
using (invoiceNumber)
group by invoicenumber

Related

How to retrieve all members from a transitive relationship through one SQL query [duplicate]

I have a table with following structure
Table name: matches
That basically stores which product is matching which product. I need to process this table
And store in a groups table like below.
Table Name: groups
group_ID stores the MIN Product_ID of the Product_IDS that form a group. To give an example let's say
If A is matching B and B is Matching C then three rows should go to group table in format (A, A), (A, B), (A, C)
I have tried looking into co-related subqueries and CTE, but not getting this to implement.
I need to do this all in SQL.
Thanks for the help .
Try this:
;WITH CTE
AS
(
SELECT DISTINCT
M1.Product_ID Group_ID,
M1.Product_ID
FROM matches M1
LEFT JOIN matches M2
ON M1.Product_Id = M2.matching_Product_Id
WHERE M2.matching_Product_Id IS NULL
UNION ALL
SELECT
C.Group_ID,
M.matching_Product_Id
FROM CTE C
JOIN matches M
ON C.Product_ID = M.Product_ID
)
SELECT * FROM CTE ORDER BY Group_ID
You can use OPTION(MAXRECURSION n) to control recursion depth.
SQL FIDDLE DEMO
Something like this (not tested)
with match_groups as (
select product_id,
matching_product_id,
product_id as group_id
from matches
where product_id not in (select matching_product_id from matches)
union all
select m.product_id, m.matching_product_id, p.group_id
from matches m
join match_groups p on m.product_id = p.matching_product_id
)
select group_id, product_id
from match_groups
order by group_id;
Sample of the Recursive Level:
DECLARE #VALUE_CODE AS VARCHAR(5);
--SET #VALUE_CODE = 'A' -- Specify a level
WITH ViewValue AS
(
SELECT ValueCode
, ValueDesc
, PrecedingValueCode
FROM ValuesTable
WHERE PrecedingValueCode IS NULL
UNION ALL
SELECT A.ValueCode
, A.ValueDesc
, A.PrecedingValueCode
FROM ValuesTable A
INNER JOIN ViewValue V ON
V.ValueCode = A.PrecedingValueCode
)
SELECT ValueCode, ValueDesc, PrecedingValueCode
FROM ViewValue
--WHERE PrecedingValueCode = #VALUE_CODE -- Specific level
--WHERE PrecedingValueCode IS NULL -- Root

Perform subquery on another subquery's result in MySQL?

Suppose there is table Product with columns prod_id, a, b
Suppose there is table Warehouse with columns w_id, pid, amount
The point is to join these two tables so that we would get in result columns prod_id, a, b, total (which is sum of the amount for pid = prod_id)
Currently I have this query:
SELECT
t1.prod_id, a, b, c AS total
FROM
(
SELECT prod_id, a, b
FROM product
WHERE ean = "3165142644363"
) t1
LEFT JOIN
(
SELECT warehouse.pid, SUM(amount) AS c
FROM warehouse
WHERE warehouse.pid IN (SELECT prod_id FROM product WHERE ean = "3165142644363")
GROUP BY warehouse.pid
) t2
ON t2.pid = t1.prod_id
Now you see there is two similar but not identical queries:
SELECT prod_id, a, b FROM product WHERE ean = "3165142644363"
SELECT prod_id FROM product WHERE ean = "3165142644363"
Executing both of these queries takes too much time. Is there a way to execute only the first one and then select product id from the result of that subquery? Or any other efficient way to rewrite the query. Creating the view is not an option as there can be many queries all with different ean parameter. The query returns more than one row of data for the same ean
I think you can remove the subquery appearing after WHERE ... IN:
SELECT
t1.prod_id, a, b, c AS total
FROM
(
SELECT prod_id, a, b
FROM product
WHERE ean = '3165142644363'
) t1
LEFT JOIN
(
SELECT warehouse.pid, SUM(amount) AS c
FROM warehouse
GROUP BY warehouse.pid
) t2
ON t2.pid = t1.prod_id
The reason you can remove it is that the t2 subquery would only contain pid values which appear in the t1 subquery. Otherwise, the sum c would just be zero anyway after the left join. A left join already implicitly handles the case where records from product may not join to anything in the t2 subquery.
That being said, removing the WHERE ... IN subquery might not improve performance that much, because it is not correlated anyway. Most likely the optimizer would only need to compute it once and cache it somewhere.
Eventually found a solution myself. Way easier than I thought:
SELECT pid, a, b, SUM(amount) AS total
FROM product
LEFT JOIN warehouse USING(pid)
WHERE ean = "3165142644363"
GROUP BY pid
In my example there are columns prod_id and pid, but in fact it is pid in both tables
Here's another formulation that might be better:
SELECT pid, a, b,
( SELECT SUM(amount)
FROM wherehouse
WHERE pid = product.prod_id
) AS total
FROM product
WHERE ean = "3165142644363";
With indexes:
product: INDEX(ean)
wherehouse: INDEX(pid, amount) -- in this order

How to select rows which have the biggest value of a column?

I don't know if my title is understandable or not, may be someone can help edit my title?
All I want to do is, for example:
I have a table like this
Engineering appears 5 times with different article_category_abbr, and I want to select only one row with the biggest value of num.
Here, it will be Engineering-ENG-192, and Geriatrics&Gerontology will be Geriatrics&Gerontology-CLM-26
But I don't know how to do it on the whole table using mysql
Join your table to a subquery which finds the greatest num value for each sc group.
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT sc, MAX(num) AS max_num
FROM yourTable
GROUP BY sc
) t2
ON t1.sc = t2.sc AND
t1.num = t2.max_num;
You can have a subquery that gets the largest value for each sc and the resulting rows will then be joined with the table itself based from two columns - sc and num.
SELECT a.*
FROM tableName a
INNER JOIN
(
SELECT sc, MAX(num) AS Num
FROM tableName
GROUP BY sc
) b ON a.sc = b.sc
AND a.num = b.num
Here's a Demo
USE MAX function and GROUP BY like this. Here is more information.
SELECT myID, classTitle, subField, MAX(score) FROM myTable GROUP BY myID, classTitle, subField

SELECT only one entry of multiple occurrences

Let's say I have a Table that looks like this:
id fk value
------------
1 1 'lorem'
2 1 'ipsum'
3 1 'dolor'
4 2 'sit'
5 2 'amet'
6 3 'consetetur'
7 3 'sadipscing'
Each fk can appear multiple times, and for each fk I want to select the last row (or more precise the row with the respectively highest id) – like this:
id fk value
------------
3 1 'dolor'
5 2 'amet'
7 3 'sadipscing'
I thought I could use the keyword DISTINCT here like this:
SELECT DISTINCT id, fk, value
FROM table
but I am not sure on which row DISTINCT will return and it must be the last one.
Is there anything like (pseudo)
SELECT id, fk, value
FROM table
WHERE MAX(id)
FOREACH DISTINCT(fk)
I hope I am making any sense here :)
thank you for your time
SELECT *
FROM table
WHERE id IN (SELECT MAX(id) FROM table GROUP BY fk)
Try this:
SELECT a.id, a.fk, a.value
FROM tableA a
INNER JOIN (SELECT MAX(a.id) id, a.fk FROM tableA a GROUP BY a.fk
) AS b ON a.fk = b.fk AND a.id = b.id;
OR
SELECT a.id, a.fk, a.value
FROM (SELECT a.id, a.fk, a.value FROM tableA a ORDER BY a.fk, a.id DESC) AS a
GROUP BY a.fk;
Try this:
SELECT t.* FROM
table1 t
JOIN (
SELECT MAX(id) as id
FROM table1
GROUP BY fk
) t1
ON t.id = t1.id
Inner query will give you highest id for each fk using MAX(). Then we join this inner table with your main table.
You could also do
SELECT id, fk, value FROM table GROUP BY fk HAVING id = MAX(id)
I don't have mysql here, but it works in Sybase ASE

need to show only the duplicate value in sql

i have table as
id----name----roll-----class
1----ram-------1-----2
2----shyam-----2-----3
3----ram-------1-----3
4----shyam-----2-----3
5----ram-------1-----2
6----hari------1-----5
i need to find the the duplicate row only that have common name, roll, class. so the expected result for me is.
id----name----roll-----class
1----ram-------1-------2
2----shyam-----2-------3
4----shyam-----2-------3
5----ram-------1-------2
i tried to get from the query below but here only one field is supported. i need all three field common. Please do help me in this. thanks
SELECT *
FROM table
WHERE tablefield IN (
SELECT tablefield
FROM table
GROUP BY tablefield
HAVING (COUNT(tablefield ) > 1)
)
You can use count() over().
select id, name, roll, class
from (select id, name, roll, class,
count(*) over(partition by name, roll, class) as c
from YourTable) as T
where c > 1
order by id
https://data.stackexchange.com/stackoverflow/query/63720/duplicates
this will retun only the duplicate entry one time:
select t.id, t.name, t.roll, t.class
from table t
inner join table t1
on t.id<t1.id
and t.name=t1.name
and t.roll = t1.roll
and t.class=t1.class
this will return what you require:
select distinct t.id, t.name, t.roll, t.class
from table t
inner join table t1
on t.name=t1.name
and t.roll = t1.roll
and t.class=t1.class
I'd suggest something like this
SELECT A.* FROM
Table A LEFT OUTER JOIN Table B
ON A.Id <> B.Id AND A.Name = B.Name AND A.Roll = B.Roll AND A.Class = B.Class
WHERE B.Id IS NOT NULL
Something like that should work (I did not test though):
select a1.*
from table a1, a2
where (a1.id != a2.id)
and (a1.name == a2.name)
and (a1.roll== a2.roll)
and (a1.class== a2.class);
It seems there are several proprosals here. If it is a query that you'll use in your code, beware of the cost of the queries. Try an 'explain' with your database.