SQL Distinct a column with conditions - mysql

I'm working on a query where I need to count distinct CarId row when the column LocationId is not null and get all CarId if its null or 0 but the query that I tried distincts all the CarId even if its null
#LocId int
Select Count(distinct a.CarId) from VehicleDetails a
inner join VehicleDocuments b on a.DocId=b.DocId
left join VehicleShipmentDetails dpg on dpg.VehicleShipmentId= b.VehicleShipmentId
where b.LogicalDelete=0 and a.LogicalDelete=0
and (dpg.LocationId= #LocId or dpg.LocationId= 0 or dpg.LocationId is null)
| ID | CarId | LocationId | DateCreated |
|------+----------------+-----------------+---------------|
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | null | 01/14/2019 |
| 3 | 2 | 0 | 02/03/2019 |
| 4 | 2 | 5 | 12/30/2018 |
| 5 | 4 | 3 | 01/10/2019 |
| 6 | 3 | 5 | 02/14/2019 |
| 7 | 2 | 5 | 03/13/2019 |
Desired output:
| ID | CarId | LocationId | DateCreated |
+------+----------------+-----------------+---------------+
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | null | 01/14/2019 |
| 3 | 2 | 0 | 02/03/2019 |
| 4 | 2 | 5 | 03/13/2019 |
| 5 | 4 | 3 | 01/10/2019 |
| 6 | 3 | 5 | 02/14/2019 |
Current Output
| ID | CarId | LocationId | DateCreated |
+------+----------------+-----------------+---------------+
| 1 | 1 | 5 | 02/03/2019 |
| 2 | 2 | 5 | 01/14/2019 |
| 3 | 4 | 3 | 01/10/2019 |
| 4 | 3 | 5 | 02/14/2019 |
Im getting a count of 4 but i needed to have 6 as the Count
EDIT: My goal is to remove the row to Distinct CarId if the value of the LocationId is Null or 0 but on my Current code, It distincts all CarId that is null,0 and equals to #LocId

You can query something like this, replace your_table by your actual set of data.
SELECT ID, CardId, LocationId, DateCreated
FROM your_table as T
WHERE NOT EXISTS (SELECT *
FROM your_table as T1
WHERE T.ID > T1.ID AND T.CarID = T1.CarID)

In SQL, you can use the statement CASE to manage conditions (just like the "if then else" in other programming languages). In your case this function could help because you have two differents cases to handle.

Related

Select ans specific value or, if not exists, the minimum one

I'm stuck trying to solve a problem using SQL (MySQL 5.6). Need to get the address which has ID 2 or, if not exists ID 2, the lower ID.
For example
|-----------------|---------------|
| CostumerID | AddressID |
|-----------------|---------------|
| 1 | 4 |
| 1 | 1 |
| 1 | 2 |
| 2 | 3 |
| 2 | 4 |
| 3 | 4 |
| 4 | 3 |
| 4 | 4 |
| 5 | 2 |
| 6 | 4 |
| 7 | 2 |
| 7 | 4 |
| 8 | 3 |
| 9 | 1 |
| 9 | 3 |
| 9 | 4 |
| 9 | 2 |
|-----------------|---------------|
If a costumerID have an AddressID 2, must get that. If not, must get the minimum AddressID.
The output must be like:
|-----------------|---------------|
| CostumerID | AddressID |
|-----------------|---------------|
| 1 | 2 |
| 2 | 3 |
| 3 | 4 |
| 4 | 3 |
| 5 | 2 |
| 6 | 4 |
| 7 | 2 |
| 8 | 3 |
| 9 | 2 |
|-----------------|---------------|
So far I've tried this:
SELECT distinct CostumerID,
if (AddressID= 2, AddressID,
(select min(b.AddressID) from Addresses b where b.AddressID= a.AddressID)) as tipus
FROM from Addresses a
but get duplicates at CostumerID.
Use aggregation with CASE logic:
SELECT
CostumerID,
CASE WHEN COUNT(CASE WHEN AddressID = 2 THEN 1 END) > 0
THEN 2 ELSE MIN(AddressID) END AS AddressID
FROM yourTable
GROUP BY
CostumerID;
SELECT CASE
WHEN EXISTS(SELECT *
FROM tbl_name
WHERE AddressID = 2)
THEN (SELECT *
FROM tbl_name
WHERE AddressID > 2 )
ELSE 'Default Value'
END

select sum of product price for every 1 id productcategory

i want to find solution for my query problem. I need to find the SUM of all priceProduct*quantity and separated with each of productcategory. I have already made a query, but it takes longer time to executed it. this is my query,
SELECT
pb.ProductCategoryID,
pb.ProductCategoryDescription,
(SELECT
SUM((SELECT pd.HPP FROM `price details` pd WHERE pd.ProductID = pdt.ProductID ORDER BY pd.PriceDetailID DESC LIMIT 1)*
(SELECT StockProductBallance FROM `stock product` sp WHERE sp.ProductID = pdt.ProductID ORDER BY sp.StockProductID DESC LIMIT 1))
FROM product pdt
WHERE pdt.ProductCategoryID = pb.ProductCategoryID
) AS Total
FROM `product category` pb
GROUP BY pb.ProductCategoryID
this my example table
table product:
+------+-------+
| id_p | id_pc |
+------+-------+
| 1 | 3 |
| 2 | 4 |
| 3 | 3 |
| 4 | 4 |
+------+-------+
table productcategory:
+-------+---------+
| id_pc | pc_name |
+-------+---------+
| 3 | new_pc |
| 4 | old_pc |
+-------+---------+
table price details:
+---------------+------+-----+
| PriceDetailID | id_p | hpp |
+---------------+------+-----+
| 1 | 1 | 100 |
| 2 | 1 | 110 |
| 3 | 1 | 120 |
| 4 | 2 | 200 |
| 5 | 2 | 210 |
| 6 | 2 | 220 |
+---------------+------+-----+
table stockProduct:
+-----------------+------+---------------+
| id_stockProduct | id_p | stockballance |
+-----------------+------+---------------+
| 1 | 1 | 10 |
| 2 | 1 | 11 |
| 3 | 1 | 12 |
| 4 | 2 | 20 |
| 5 | 2 | 21 |
| 6 | 2 | 22 |
+-----------------+------+---------------+
Really need your help guys, for better query..

MySQL complex ORDER BY issue

I have a complicated ordering issue in my query.
Raw, Unordered Data:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 3 | 1 | 1 |
| 4 | 2 | 3 |
| 5 | 4 | 1 |
| 6 | 1 | 2 |
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| 9 | 4 | 2 |
+------+--------+-----------+
Required Ordering:
+------+--------+-----------+
| id | job_id | action_id |
+------+--------+-----------+
| 7 | 3 | 1 |
| 8 | 3 | 2 |
| | | | * blank lines added for clarity,
| 5 | 4 | 1 | not desired in actual data
| 9 | 4 | 2 |
| | | |
| 3 | 1 | 1 |
| 6 | 1 | 2 |
| | | |
| 1 | 2 | 1 |
| 2 | 2 | 2 |
| 4 | 2 | 3 |
+------+--------+-----------+
The theory behind this ordering:
the largest id is the most recently added entry
the most recent id with action_id of 1
followed by the entries with ascending action_ids that have the same job_id
then the next most recent action_id of 1
ad infinitum
EDIT: I'm not able to add columns to the table in order to aid in sorting, as I've seen in some other solutions to ordering questions.
Any help is greatly appreciated!
My best shot is this:
SELECT * FROM tbl
ORDER BY FIND_IN_SET(job_id,
(SELECT GROUP_CONCAT(job_id ORDER BY ID DESC)
FROM tbl WHERE action_id = 1));
I didn't find a way to do it easily, What do you think of the following code :
select c.id, c.job_id, c.action_id
from (select a.id, a.job_id, a.action_id, min(b.id) as related_id
from myTable a
inner join myTable b
on a.job_id=b.job_id
group by a.job_id) c
group by c.id
order by c.related_id desc, c.action_id

Updating multiple rows with first instance of record in same table

Assume following table:
+----+-----------+
| id | session |
+----+-----------+
| 1 | abcd1234 |
| 2 | abcd1234 |
| 3 | abcd1234 |
| 4 | qwert5678 |
| 5 | qwert5678 |
| 6 | abcd1234 |
| 7 | abcd1234 |
| 8 | qwert5678 |
| 9 | abcd1234 |
| 10 | qwert5678 |
| 11 | qwert5678 |
| 12 | qwert5678 |
+----+-----------+
Suppose we want to get the first id of a given session, then set every instance of that session to the id for all sessions, such that the table becomes:
+----+-----------+
| id | session |
+----+-----------+
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 4 |
| 5 | 4 |
| 6 | 1 |
| 7 | 1 |
| 8 | 4 |
| 9 | 1 |
| 10 | 4 |
| 11 | 4 |
| 12 | 4 |
+----+-----------+
We have a table with approximately 45M records, and are essentially changing every instance of column b to the value of min(column a) when grouped by column b.
Is there a way to do this in a single query? We have attempted several.
update example e
set session =
(select id from
(select id,min(session)
from example as first_id
group by session
) as this_id
);
...which errors out: "Subquery returns more than 1 row".
update example e
join
(select id
from
(select id,min(session)
from example as first_id
group by session
) as this_id
) as etable
set session = first_id;
...which errors out: "Unknown column 'first_id' in 'field list'". Also used 'this_id' to the same effect.
And other queries. Is this possible in a single query? Are we thinking about this incorrectly?
Query:
SQLFIDDLEExample
UPDATE example
SET session =(SELECT MIN(e2.ID)
FROM (SELECT *
FROM example) e2
WHERE e2.session = example.session)
Result:
| ID | SESSION |
----------------
| 1 | 1 |
| 2 | 1 |
| 3 | 1 |
| 4 | 4 |
| 5 | 4 |
| 6 | 1 |
| 7 | 1 |
| 8 | 4 |
| 9 | 1 |
| 10 | 4 |
| 11 | 4 |
| 12 | 4 |

Limiting MySQL results based on a field

I've table called Products in that type is field type value might be any one of these values 1,2,3,4.
Now I'would like to get the result as
1. Group the results based on 'type'
2. And Limit the results for each group to 5.
How can I achieve this, Currently I'm using following query
SELECT
*,
(
(
CASE
WHEN product_title LIKE '%xyz%'
THEN 2
ELSE 0
END
) + (
CASE
WHEN product_description LIKE '%xyz%'
THEN 1
ELSE 0
END
)
) AS relevance
FROM
Products
WHERE (
(
product_title LIKE '%xyz%'
OR product_description LIKE '%xyz%'
)
)
AND product_available = 1
AND product_deleted <> 1
ORDER BY relevance DESC
SELECT * FROM products;
+------------+------+
| product_id | type |
+------------+------+
| 1 | 4 |
| 2 | 3 |
| 3 | 2 |
| 4 | 4 |
| 5 | 3 |
| 6 | 1 |
| 7 | 4 |
| 8 | 3 |
| 9 | 4 |
| 10 | 2 |
| 11 | 2 |
| 12 | 1 |
| 13 | 3 |
| 14 | 2 |
| 15 | 3 |
| 16 | 1 |
| 17 | 2 |
| 18 | 1 |
| 19 | 2 |
| 20 | 4 |
| 21 | 2 |
+------------+------+
SELECT x.*
FROM products x
JOIN products y
ON y.type = x.type
AND y.product_id <= x.product_id
GROUP
BY x.product_id
HAVING COUNT(*) <=3
ORDER
BY type
, product_id;
+------------+------+
| product_id | type |
+------------+------+
| 6 | 1 |
| 12 | 1 |
| 16 | 1 |
| 3 | 2 |
| 10 | 2 |
| 11 | 2 |
| 2 | 3 |
| 5 | 3 |
| 8 | 3 |
| 1 | 4 |
| 4 | 4 |
| 7 | 4 |
+------------+------+
Here's a simple one
SELECT
p.id,
p.type
FROM
Products p
WHERE
5 > (SELECT COUNT(id) from Products where id < p.id and type = p.type)
I have created the sqlfiddle for it, http://sqlfiddle.com/#!2/ab0c00/15