LeftJoin Minus (Right Table data + inner join Data) - mysql

TABLE 1)
m_conservationsetting
+------------+-------+------------+
| FacilityId | Unit | CategoryId |
+------------+-------+------------+
| 1 | 1 | 1 |
| 1 | 1 | 2 |
| 1 | 1 | 3 |
| 1 | 2 | 1 |
| 1 | 2 | 2 |
| 2 | 1 | 1 |
| 2 | 2 | 1 |
+------------+-------+------------+
Unique Key(FacilityId Unit CategoryId)
TABLE 2)
l_maintelog
+------------+------+------------+--------+
| FacilityId | Unit | CategoryId | Status |
+------------+------+------------+--------+
| 1 | 1 | 1 | 0 |
| 1 | 1 | 2 | 1 |
| 1 | 1 | 3 | 0 |
| 1 | 2 | 1 | 0 |
| 2 | 1 | 1 | 0 |
| 2 | 2 | 1 | 0 |
+------------+------+------------+--------+
Result :
+------------+------+------------+
| FacilityId | Unit | CategoryId |
+------------+------+------------+
| 1 | 1 | 2 |
| 1 | 2 | 2 |
+------------+------+------------+
Table1 need to be left Joined with Table2 and it should ommit the join results and show only table1 data as results.
Table1 LeftJoin Table2 - (join Data) for the below query. The condition for getting result is to check the status=0 for the record in Table2
Query
select cs.FacilityId,Cs.Unit,cs.CategoryId
from m_conservationsetting cs
LEFT JOIN l_maintelog ml on
(cs.FacilityId=ml.FacilityId and cs.Unit=ml.Unit)
WHERE (ml.Status=0
)
group by cs.CategoryId

You can use NULL conditional on Second Table's Key column to eliminate result which is there in both tables
Select cs.FacilityId,Cs.Unit,cs.CategoryId
from m_conservationsetting cs
LEFT JOIN l_maintelog ml on
(cs.FacilityId=ml.FacilityId and cs.Unit=ml.Unit)
WHERE (ml.Status=0
and ml.FacilityId IS NULL)
group by cs.CategoryId

Related

SQL Distinct a column with conditions

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.

Calculate percentages by group using sql

I have a table that cotains the id of the students, the course name and the course level.
+----+--------+-------+
| Id | Course | Level |
+----+--------+-------+
| 1 | A | 1 |
| 2 | A | 1 |
| 1 | B | 1 |
| 3 | B | 1 |
| 4 | C | 2 |
+----+--------+-------+
From this, I want to know the percentage each course covers by level.
Like in the below table:
+-------+--------+----------------+
| Level | Course | Count_by_level |
+-------+--------+----------------+
| 1 | A | 50% |
| 1 | A | 50% |
| 1 | B | 50% |
| 1 | B | 50% |
| 2 | C | 100% |
+-------+--------+----------------+
How can I do this using SQL?
SQL DEMO
SELECT S.[Id] , S.[Course], S.[Level], T.ctotal,
100.0 / T.ctotal
FROM students S
JOIN ( SELECT [Course], COUNT(*) as ctotal
FROM students
GROUP BY [Course]
) T
ON S.[Course] = T.[Course]
OUTPUT
| Id | Course | Level | ctotal | |
|----|--------|-------|--------|-----|
| 1 | A | 1 | 2 | 50 |
| 2 | A | 1 | 2 | 50 |
| 1 | B | 1 | 2 | 50 |
| 3 | B | 1 | 2 | 50 |
| 4 | C | 2 | 1 | 100 |
Just another option using the window functions (assuming 2012+)
Example
Select [Level]
,[Course]
,Pct = 100.0 / sum(1) over (partition by [Level],[Course])
From YourTable
Returns
Level Course Pct
1 A 50.000000
1 A 50.000000
1 B 50.000000
1 B 50.000000
2 C 100.000000

Select Same Column From 2 Tables into 1 Column in View

I have two column with the same name in different tables.
I want to join them into one column in a view.
Here my first table stocks:
+----------+------------+------------+---------+----------------+--------+
| stock_id | stock_cost | stock_left | item_id | purchasedtl_id | trx_id |
+----------+------------+------------+---------+----------------+--------+
| 1 | 1000 | 0 | 1 | 1 | 1 |
| 2 | 1000 | 5 | 1 | 2 | 2 |
| 3 | 1000 | 1 | 1 | 3 | 4 |
+----------+------------+------------+---------+----------------+--------+
Second table stocks_out
+-------------+----------------+--------------+---------+----------+------------+--------+
| stockout_id | stockout_price | stockout_qty | item_id | stock_id | saledtl_id | trx_id |
+-------------+----------------+--------------+---------+----------+------------+--------+
| 1 | 2000 | 1 | 1 | 1 | 1 | 3 |
+-------------+----------------+--------------+---------+----------+------------+--------+
And I want to join them to be like this trx_id, trx_no, trx_closetime, trx_type stock_id, stock_cost, stockout_id, stock_out_cost, stockout_price, item_id
item_id is the field I want to join in one column.
The current Query is :
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price` from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the current result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+
Found it guys.
I just need to add the following query as the column
COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id`
So the query will be like
select `transactions`.`trx_id` AS `trx_id`,`transactions`.`trx_no` AS `trx_no`,`transactions`.`trx_closetime` AS `trx_closetime`,`transactions`.`trx_type` AS `trx_type`,`stocks`.`stock_id` AS `stock_id`,`stocks`.`stock_cost` AS `stock_cost`,`stock_out`.`stockout_id` AS `stockout_id`,`stock_out`.`stockout_price` AS `stockout_price`, COALESCE(`stocks`.`item_id`, `stocks_out`.`item_id`) AS `item_id from ((`transactions` left join `stocks` on(`stocks`.`trx_id` = `transactions`.`trx_id`)) left join `stock_out` on(`stock_out`.`trx_id` = `transactions`.`trx_id`)) order by `transactions`.`trx_closetime`;
And the result:
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| trx_id | trx_no | trx_closetime | trx_type | stock_id | stock_cost | stockout_id | stockout_price | item_id |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+
| 1 | 02002-02-170415-001 | 2017-04-15 19:40:03 | 2 | 1 | 1000 | NULL | NULL | 1 |
| 2 | 02002-02-170415-002 | 2017-04-15 19:40:13 | 2 | 2 | 1000 | NULL | NULL | 1 |
| 3 | 02002-01-170415-001 | 2017-04-15 19:40:57 | 1 | NULL | NULL | 1 | 2000 | 1 |
| 4 | 02002-02-170415-003 | 2017-04-15 19:41:14 | 2 | 3 | 1000 | NULL | NULL | 1 |
+--------+---------------------+---------------------+----------+----------+------------+-------------+----------------+---------+

SQL - filter duplicate rows based on a value in a different column

I have an SQL table:
+-------------+-----------+---------+
| ID | position | user |
+-------------+-----------+---------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 |
| 6 | 6 | 0 |
| 7 | 7 | 0 |
| 8 | 7 | 1 |
+-------------+-----------+---------+
I would like to filter the duplicate row based on position column and the distinct value of user column, for the first query I need to have the following result:
+-------------+-----------+---------+
| ID | position | user |
+-------------+-----------+---------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 |
| 6 | 6 | 0 |
| 8 | 7 | 1 |
+-------------+-----------+---------+
For the second query I need the following:
+-------------+-----------+---------+
| ID | position | user |
+-------------+-----------+---------+
| 1 | 1 | 0 |
| 2 | 2 | 0 |
| 3 | 3 | 0 |
| 4 | 4 | 0 |
| 5 | 5 | 0 |
| 6 | 6 | 0 |
| 7 | 7 | 0 |
+-------------+-----------+---------+
What queries do I need to achieve this?
Thanks.
In the absence of further information, the two queries below assume that you want to resolve duplicate positions by taking either the larger (maximum) user value, in the first case, or the smaller (minimum) user value in the second case.
First query:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT position, MAX(user) AS max_user
FROM yourTable
GROUP BY position
) t2
ON t1.position = t2.position AND
t1.user = t2.max_user
Second query:
SELECT t1.*
FROM yourTable t1
INNER JOIN
(
SELECT position, MIN(user) AS min_user
FROM yourTable
GROUP BY position
) t2
ON t1.position = t2.position AND
t1.user = t2.min_user

How to return row of sum()s

I now find my original table structure was not good, so want to change it.
But I am having a hard time designing queries to obtain totals in rows with the new structure.
current structure:
+----------+-------+-------+-------+-------+
| state | shop | item0 | item1 | item2 |
+----------+-------+-------+-------+-------+
| 5 | 0 | 1 | 2 | 3 |
| 5 | 1 | 1 | 2 | 3 |
| 5 | 2 | 1 | 2 | 3 |
| 4 | 3 | 1 | 2 | 3 |
+----------+-------+-------+-------+-------+
(quantities of items at shop)
I want to change to these 2 tables:
shops table
+---------+--------+
| shop_id | state |
+---------+--------+
| 0 | 5 |
| 1 | 5 |
| 2 | 5 |
| 3 | 4 |
+---------+--------+
items table
+------------+--------------+
| shop | item | quantity |
+------------+--------------+
| 0 | 0 | 1 |
| 0 | 1 | 2 |
| 0 | 2 | 3 |
| 1 | 0 | 1 |
| 1 | 1 | 2 |
| 1 | 2 | 3 |
| 2 | 0 | 1 |
| 2 | 1 | 2 |
| 2 | 2 | 3 |
| 3 | 0 | 1 |
| 3 | 1 | 2 |
| 3 | 2 | 3 |
+------------+--------------+
The old layout allowed simple queries for getting totals by row:
SELECT state,SUM(item0) t0,SUM(item1) t1,SUM(item2) t2
FROM shops
WHERE state=5
+--------+---------+---------+----------+
| state | t0 | t1 | t2 |
+--------+---------+---------+----------+
| 5 | 3 | 6 | 9 |
+--------+---------+---------+----------+
With the new structure,
I can get the totals in column as follows:
SELECT item,SUM(quantity) total
FROM shops
LEFT JOIN items ON shop=shopid
WHERE state=5
GROUP by item
+--------+---------+
| item | total |
+--------+---------+
| 0 | 3 |
+--------+---------+
| 1 | 6 |
+--------+---------+
| 2 | 9 |
+--------+---------+
but how do I get the totals in rows:
+--------+---------+---------+----------+
| state | t0 | t1 | t2 |
+--------+---------+---------+----------+
| 4 | 1 | 2 | 3 |
| 5 | 3 | 6 | 9 |
+--------+---------+---------+----------+
You might try using a few more JOINs:
SELECT S.state,
SUM(T0.quantity) AS "T0",
SUM(T1.quantity) AS "T1",
SUM(T2.quantity) AS "T2"
FROM shops AS S
LEFT JOIN items AS T0 ON S.shop_id = T0.shop_id AND T0.item=0
LEFT JOIN items AS T1 ON S.shop_id = T1.shop_id AND T1.item=1
LEFT JOIN items AS T2 ON S.shop_id = T2.shop_id AND T2.item=2
GROUP BY S.state
There might be an easier way.