selecting unique ids from two rows - mysql

ok so table looks like this
owner_id | creator_id | receiver_id | content | created
1 | 1 | 2 | hoho | 2011-27-05
2 | 1 | 2 | hoho | 2011-27-05
1 | 2 | 1 | eoeo | 2011-28-05
2 | 2 | 1 | eoeo | 2011-28-05
1 | 1 | 3 | aaaa | 2011-29-05
3 | 1 | 3 | aaaa | 2011-29-05
2 | 2 | 3 | bbbb | 2011-30-05
3 | 2 | 3 | bbbb | 2011-30-05
what I would like is to select only the last record for owner_id = 1 from each creator_id OR receiver_id and it doesn't matter is it last from creator_id or receiver_id as long it is last record where unique creator_id or receiver_id is.
do the result should look like this
owner_id | creator_id | receiver_id | content | created
1 | 1 | 3 | aaaa | 2011-29-05
1 | 2 | 1 | eoeo | 2011-28-05

Start by fetching the last date per owner_id, creator_id:
select owner_id,
creator_id as user_id,
max(created) as max_created
from data
where owner_id = 1
group by owner_id, creator_id
And the same per owner_id, receiver_id:
select owner_id,
receiver_id as user_id,
max(created) as max_created
from data
where owner_id = 1
group by owner_id, receiver_id
Then union and apply the max another time:
select owner_id, user_id, max(max_created) as max_created
from (
[the first of the above]
union all
[the second of the above]
) as users
group by owner_id, user_id
Then join it in a subquery:
select data.*
from data
join ([the union query above]) as max_dates
on max_dates.owner_id = data.owner_id
and max_dates.user_id in (data.creator_id, data.reporter_id)
and max_dates.max_created = data.created
where owner_id = 1 -- avoids scanning the whole table
That'll yield the rows where creator_id appeared last, and those where reporter_id appeared last.
You cannot reduce it further without dropping valid rows. Suppose the returned (creator/reporter) pairs are (1,2) and (2,1). Then both rows would be eliminated if you sought the absolute last appearance of each user.

Related

How to select sum of specific id in select query MySQL, Beego

I want to get a result like
result
-------------------------------------------------------
id | uuid | user_id |created_date | amount | name
-------------------------------------------------------
1 | ABC | 1 | 2019/5/1 | 5 | xa
2 | PQR | 2 | 2019/5/5 | 150 | xb
A query that I trying to use
SELECT(SELECT SUM(paid_amount) WHERE ID = t1.**HERE**) AS sub1,
(t1.amount - sub1) AS sub2
FROM invoice t1 CROSS JOIN
invoice_paid t2;
Table struct in my DB
table invoice_paid
------------------------------------
id | uuid | paid_date | paid_amount
------------------------------------
1 | ABC | 2019/5/1 | 15
2 | ABC | 2019/5/5 | 80
table invoice
-------------------------------------------------------
id | uuid | user_id |created_date | amount | name
-------------------------------------------------------
1 | ABC | 1 | 2019/5/1 | 100 | xa
2 | PQR | 2 | 2019/5/5 | 150 | xb
I can use sum only 1 condition like where id = 1 but how do I combine this query in select query with a join query.
I use beego(golang), MariaDB
You can use this query. It JOINs the invoice table to a derived table of SUMs of all the amounts paid per invoice from invoice_paid, subtracting that total from the invoice amount to get the outstanding amount:
SELECT i.id, i.uuid, i.user_id, i.created_date, i.amount - COALESCE(p.amount, 0) AS amount, i.name
FROM invoice i
LEFT JOIN (SELECT uuid, SUM(paid_amount) AS amount
FROM invoice_paid
GROUP BY uuid) p ON p.uuid = i.uuid
ORDER BY i.id
Output:
id uuid user_id created_date name amount
1 ABC 1 2019-05-01 00:00:00 xa 5
2 PQR 2 2019-05-05 00:00:00 xb 150
Demo on dbfiddle

Select * from 2 tables where CatergoryID's are 1

I've got these tables:
table : _newapp_shop_products_events
+-------+-----------+-----------+-------------------+
| EventID | categoryID | Price |
+-------+-----------+-----------+-------------------+
| 9050 | 1 | 15.00 |
| 5048 | 2 | 12.00 |
+-------+-----------+-----------+-------------------+
table : _newapp_shop_products_categories
+-------+-----------+-----------+-------------------+
| CategoryID | Category_Name | photo |
+-------+-----------+-----------+-------------------+
| 1 | Tickets | one.jpg |
| 2 | Voucher | two.jpg |
+-------+-----------+-----------+-------------------+
table : _newapp_shop_products_activitys
+-------+-----------+-----------+-------------------+
| ActivityID | categoryID | Price |
+-------+-----------+-----------+-------------------+
| 80 | 1 | 13.00 |
| 95 | 2 | 18.00 |
+-------+-----------+-----------+-------------------+
And these are linked by a relationship, categories -> events, categories -> activities.
I want to display events and activities (the Events and Activity Tables not the _newapp ones) in one list and only display the items from both tables with categoryID = 1 for example. How would I solve this?
I have tried to join them or select them both in a union, it returns the rows fine but the internal link within mysql is broken. when I click on the second result set from 'Activitys' the id is correct and the price but when i click the id to go to the corresponding id it gives 0 rows result as it generates the query: SELECT * FROM representin_nl_-_1.Events WHERE Id = 5 But that is the wrong table, it should search it in SELECT * FROM representin_nl_-_1._newapp_shop_products_activitys WHERE Id = 5 instead. Result: The first 9050 when i click it, it goes to the correct row but the ids after that are not found. Result:
You probably want a UNION
SELECT 'Event' AS Type, EventID AS Id, Price
FROM Events
WHERE CategoryId = 1
UNION ALL
SELECT 'Activity' AS Type, ActivityID AS Id, Price
FROM Activity
WHERE CategoryId = 1
What do you mean Id conflict? You could do something like this instead
SELECT EventID, null AS ActivityId, Price
FROM Events
WHERE CategoryId = 1
UNION ALL
SELECT null, ActivityID, Price
FROM Activity
WHERE CategoryId = 1

Count the number of orders

I have a table (Table1) with the columns order_item_id customer_id and order_id in which I want to count the number of orders per customer. Unfortunately an order with more than one article has the same order_id
|order_item_id|order_id|customer_id|
| 2 | 30 | 1 |
| 3 | 30 | 1 |
| 4 | 42 | 1 |
| 5 | 33 | 2 |
| 11 | 32 | 3 |
| 12 | 33 | 2 |
| 13 | 33 | 2 |
| 19 | 69 | 3 |
Expected Outcome:
|numberOfOrders|customer_id|
| 2 | 1 |
| 1 | 2 |
| 2 | 3 |
I tried this (and many more):
CREATE TABLE X AS
SELECT
customer_id,
COUNT(order_id) AS `numberOfOrders`
FROM Table1 T1
GROUP BY customer_id;
The problem is, that with this solution it counts every article not the number of orders: so the number of orders for customer 1 is 3 (not 2), for customer 2 is 3 (not 1)....
How can I solve this for a big database with Mysql query?
Try the following solution to SELECT your data as expected:
SELECT COUNT(DISTINCT order_id) AS numberOfOrders, customer_id
FROM table1
GROUP BY customer_id
Demo: http://sqlfiddle.com/#!9/ee8f62/1/0
An option could be to do GROUP twice. First GROUP for the number of items per order, wrapped by a second GROUP for the number of orders per customer:
/* second group */
SELECT customer_id
, count(*) AS number_of_orders
FROM (
/* first group */
SELECT order_id
, customer_id
, count(*) AS order_item_count
FROM Table1
GROUP BY order_id, customer_id
) a
GROUP BY customer_id

Finding duplicates from two columns, but show all rows MySQL

I have a table like this
| user_id | company_id | employee_id |
|---------|------------|-------------|
| 1 | 2 | 123 |
| 2 | 2 | 123 |
| 3 | 5 | 432 |
| 4 | 5 | 432 |
| 5 | 7 | 432 |
I have a query that looks like this
SELECT COUNT(*) AS Repeated, employee_id, GROUP_CONCAT(user_id) as user_ids, GROUP_CONCAT(username)
FROM user_company
INNER JOIN user ON user.id = user_company.user_id
WHERE employee_id IS NOT NULL
AND user_company.deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING Repeated >1;
The results I am getting look like this
| Repeated | employee_id | user_ids |
|---------|--------------|------------|
| 2 | 123 | 2,3 |
| 2 | 432 | 7,8 |
I need results that look like this
| user_id |
|---------|
| 2 |
| 3 |
| 7 |
| 8 |
I realize my query is getting more, but that's just to make sure I'm getting the correct data. Now I need to get a single column result with each user_id in a new row for updating based on user_id in another query. I've tried this by only selecting the user_id but I only get two rows, I need all four rows of duplicates.
Any ideas on how to modify my query?
Here is the query to get all of your user_ids:
SELECT user_id
FROM user_company uc
INNER JOIN
(
SELECT employee_id, company_id
FROM user_company
WHERE employee_id IS NOT NULL
AND deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING COUNT(employee_id) >1
) AS `emps`
ON emps.employee_id = uc.`employee_id`
AND emps.company_id = uc.`company_id`;
This query below will generate the query you are looking for.
SELECT CONCAT('UPDATE user_company SET employee_id = null WHERE user_id IN (', GROUP_CONCAT(user_id SEPARATOR ', '),')') AS user_sql
FROM user_company uc
INNER JOIN
(SELECT employee_id, company_id
FROM user_company
WHERE employee_id IS NOT NULL
AND deleted_at IS NULL
GROUP BY employee_id, company_id
HAVING COUNT(employee_id) >1) AS `emps`
ON emps.employee_id = uc.`employee_id`
AND emps.company_id = uc.`company_id`;

how to find duplicates and gaps in this scenario in mysql

Hi I have a table that looks like
-----------------------------------------------------------
| id | group_id | source_id | target_id | sortsequence |
-----------------------------------------------------------
| 2 | 1 | 2 | 4 | 1 |
-----------------------------------------------------------
| 4 | 1 | 20 | 2 | 1 |
-----------------------------------------------------------
| 5 | 1 | 2 | 14 | 1 |
-----------------------------------------------------------
| 7 | 1 | 2 | 7 | 3 |
-----------------------------------------------------------
| 20 | 2 | 20 | 4 | 3 |
-----------------------------------------------------------
| 21 | 2 | 20 | 4 | 1 |
-----------------------------------------------------------
Scenario
There are two scenarios that needs to be handled.
Sortsequence column value should be unique against one source_id and group_id. For example if all the records having group_id = 1 AND source_id = 2 should have sortsequence unique. In above example records having id= and 5 which are having group_id = 1 and source_id = 2 have same sortsequence which is 1. This is faulty record. I need to find out these records.
If group_id and source_id is same. The sortsequence columns value should be continous. There should be no gap. For example in above table records having id = 20, 21 having same group_id and source_id and sortsequence value is 3 and 1. Even this is unique but there is a gap in sortsequence value. I need to also find out these records.
MY So Far Effort
I have written a query
SELECT source_id,`group_id`,GROUP_CONCAT(id) AS children
FROM
table
GROUP BY source_id,
sortsequence,
`group_id`
HAVING COUNT(*) > 1
This query only address the scenario 1. How to handle scenario 2? Is there any way to do it in same query or I have to write other to handle second scenario.
By the way query will be dealing with million of records in table so performance must be very good.
Got answer from Tere J Comments. Following query covers above mentioned both criteria.
SELECT
source_id, `group_id`, GROUP_CONCAT(id) AS faultyIDS
FROM
table
GROUP BY
source_id,group_id
HAVING
COUNT(DISTINCT sortsequence) <> COUNT(sortsequence) OR COUNT(sortsequence) <> MAX(sortsequence) OR MIN(sortsequence) <> 1
May be it can help others.
Try this query it will solve both of the cases as you have mentioned in the question.
SELECT
a.*
FROM
tbl a
INNER JOIN
(select
#rn:=IF(#prevG = group_id AND #prevS = source_id, #rn + 1, 1) As rId,
#prevG:=group_id AS group_id,
#prevS:=source_id AS source_id,
id,
sortsequence
FROM
tbl
join
(select #rn:=0, #prevS:=0, #prevG:=0)b
order by group_id, source_id, id) b
ON a.id = b.id AND a.SORTSEQUENCE <> b.RID;
FIDDLE