MySQL - Get all rows from left table per group on right table - mysql

I need to show all records from table A per user_id in table B, even if not matched. I have tried with LEFT JOIN and GROUP-ing but did not achieved my expected result. Also my skill on SQL is not good, so need help.
Here is my table data:
Table A : gateways
=========================
| ID | Gateway |
=========================
| 1 | Paypal |
| 2 | Webpay |
| 3 | Stripe |
=========================
Table B : gateway_user
==================================
| GatewayID | UserID | Active |
==================================
| 1 | 1 | Y |
| 1 | 2 | Y |
| 1 | 3 | N |
| 2 | 1 | Y |
| 2 | 2 | N |
| 3 | 1 | Y |
==================================
The result I expect is to see all results from left table per user_id on right, even if it doesn't exist in Right Table.
==================================
| GatewayID | UserID | Active |
==================================
| 1 | 1 | Y |
| 1 | 2 | Y |
| 1 | 3 | N |
| 2 | 1 | Y |
| 2 | 2 | N |
| 2 | 3 | null |
| 3 | 1 | Y |
| 3 | 2 | null |
| 3 | 3 | null |
==================================
Thank you.

You have to create artificial table containing list of all userId:
SELECT gw.id, ua.userId, gu.active
FROM gateways gw
JOIN (SELECT DISTINCT userId
FROM gateway_user) ua
LEFT JOIN gateway_user gu
ON gu.userId = ua.userId AND gu.gatewayId = gw.gatewayId

Related

Oracle 12 - How to identify duplicates with increment?

I want to differentiate duplicate values in my query by adding an increment or a count of some sort.
The idea is to concatenate my two columns to create a new unique reference.
I tried this :
SELECT
value,
COUNT(*) OVER (PARTITION BY value) value_incr
FROM table
and got the following result :
| value | value_incr |
| --- | --- |
| a | 1 |
| b | 3 |
| b | 3 |
| b | 3 |
| c | 2 |
| c | 2 |
| d | 1 |
But what I would like to get is :
| value | value_incr |
| --- | --- |
| a | 1 |
| b | 1 |
| b | 2 |
| b | 3 |
| c | 1 |
| c | 2 |
| d | 1 |
Is there a way to differentiate my duplicates in Oracle 12 ?
My best solution for now is to add a ROWNUM column, but it's not really satisfying.
Thank you

Query equivalent to two group by's without a subquery?

I'm trying to run a report on User ACL's. We use MYSQL and my we're prohibited from using subqueries for performance reasons. The goal is to turn this:
--------------------------------
| userName | folderID | roleID |
--------------------------------
| gronk | 1 | 1 |
| gronk | 2 | 2 |
| gronk | 4 | 2 |
| tbrady | 1 | 2 |
| jedelman | 1 | 1 |
| jedelman | 2 | 1 |
| mbutler | 1 | 2 |
| mbutler | 2 | 2 |
| bill | 1 | 3 |
| bill | 2 | 3 |
| bill | 3 | 3 |
| bill | 4 | 3 |
--------------------------------
Into this:
------------------------
| Lowest Role | Number |
------------------------
| 1 | 2 |
| 2 | 2 |
| 3 | 1 |
------------------------
I can see how to do it with a subquery. The inner query would do a group by on userName with a min(roleID). Then the outer query would do a group by on the lowest role and count(*). But I can't see how to do it without a subquery.
Also, if it helps I created a SQL Fiddle that has the data above.
I found a solution using a left join:
select UFM.roleID, count(distinct UFM.userName)
from UserFolderMembership UFM
left join UserFolderMembership UFM2 on
UFM.userName = UFM2.userName and
UFM.roleID > UFM2.roleID
where
UFM2.userName is null
group by
UFM.roleID

How to get count of combinations from database?

How to get count of combinations from database?
I have to database tables and want to get the count of combinations. Does anybody know how to put this in a database query, therefore I haven't a db request for each trip?
Trips
| ID | Driver | Date |
|----|--------|------------|
| 1 | A | 2015-12-15 |
| 2 | A | 2015-12-16 |
| 3 | B | 2015-12-17 |
| 4 | A | 2015-12-18 |
| 5 | A | 2015-12-19 |
Passengers
| ID | PassengerID | TripID |
|----|-------------|--------|
| 1 | B | 1 |
| 2 | C | 1 |
| 3 | D | 1 |
| 4 | B | 2 |
| 5 | D | 2 |
| 6 | A | 3 |
| 7 | B | 4 |
| 8 | D | 4 |
| 9 | B | 5 |
| 10 | C | 5 |
Expected result
| Driver | B-C-D | B-D | A | B-C |
|--------|-------|-----|---|-----|
| A | 1 | 2 | - | 1 |
| B | - | - | 1 | - |
Alternative
| Driver | Passengers | Count |
|--------|------------|-------|
| A | B-C-D | 1 |
| A | B-D | 2 |
| A | B-C | 1 |
| B | A | 1 |
Has anybody an idea?
Thanks a lot!
Try this:
SELECT Driver, Passengers, COUNT(*) AS `Count`
FROM (
SELECT t.ID, t.Driver,
GROUP_CONCAT(p.PassengerID
ORDER BY p.PassengerID
SEPARATOR '-') AS Passengers
FROM Trips AS t
INNER JOIN Passengers AS p ON t.ID = p.TripID
GROUP BY t.ID, t.Driver) AS t
GROUP BY Driver, Passengers
The above query will produce the alternative result set. The other result set can only be achieved using dynamic sql.
Demo here

Complex MySQL Query for Many-to-Many

I have searched and gone through the available topics similar to mine. But, failed to find that satisfies my requirements. Hence, posting it here.
I have four tables as follows:
"Organization" table:
--------------------------------
| org_id | org_name |
| 1 | A |
| 2 | B |
| 3 | C |
"Members" table:
----------------------------------------------
| mem_id | mem_name | org_id |
| 1 | mem1 | 1 |
| 2 | mem2 | 1 |
| 3 | mem3 | 2 |
| 4 | mem4 | 3 |
"Resource" table:
--------------------------------
| res_id | res_name |
| 1 | resource1 |
| 2 | resource2 |
| 3 | resource3 |
| 4 | resource4 |
"member-resource" table:
--------------------------------------------
| sl_no | mem_id | res_id |
| 1 | 1 | 1 |
| 2 | 1 | 2 |
| 3 | 2 | 1 |
| 4 | 4 | 3 |
| 5 | 3 | 4 |
| 6 | 2 | 3 |
| 7 | 4 | 3 |
I want to find out the total number of distinct resources according to organizations. Expected output is as follows:
| org_name | Total Resources |
| A | 3 |
| B | 1 |
| C | 1 |
I also want to find out the total number of shared resources according to organizations. Expected output is as follows:
| org_name | Shared Resources |
| A | 1 |
| B | 0 |
| C | 1 |
Any help in this regard will highly be appreciated.
Regards.
It is much simpler than you think, particularly because you don't even need the resource table:
SELECT o.org_name, COUNT(DISTINCT mr.res_id) TotalResources
FROM member_resource mr
JOIN members m ON mr.mem_id = m.mem_id
JOIN organization o ON m.org_id = o.org_id
GROUP BY o.org_id
Output:
| ORG_NAME | TOTALRESOURCES |
|----------|----------------|
| A | 3 |
| B | 1 |
| C | 1 |
Fiddle here.
Try this query below.
SELECT org_name, COUNT(DISTINCT res_id)
FROM organization, members, member-resource
WHERE members.mem_id = member-resource.mem_id
AND organization.org_id = members.org_id
GROUP BY org_id, org_name

Is there a way in SQL (MySQL) to do a "round robin" ORDER BY on a particular field?

Is there a way in SQL (MySQL) to do a "round robin" ORDER BY on a particular field?
As an example, I would like to take a table such as this one:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 1 | B |
| 1 | C |
| 2 | D |
| 2 | E |
| 2 | F |
| 3 | G |
| 3 | H |
| 3 | I |
+-------+------+
And run a query that produces results in this order:
+-------+------+
| group | name |
+-------+------+
| 1 | A |
| 2 | D |
| 3 | G |
| 1 | B |
| 2 | E |
| 3 | H |
| 1 | C |
| 2 | F |
| 3 | I |
+-------+------+
Note that the table may have many rows, so I can't do the ordering in the application. (I'd obviously have a LIMIT clause as well in the query).
I'd try something like:
SET #counter = 0;
SELECT (#counter:=#counter+1)%3 as rr, grp, name FROM table ORDER by rr, grp
What you can do is create a temporary column in which you create sets to give you something like this:
+-------+------+-----+
| group | name | tmp |
+-------+------+-----+
| 1 | A | 1 |
| 1 | B | 2 |
| 1 | C | 3 |
| 2 | D | 1 |
| 2 | E | 2 |
| 2 | F | 3 |
| 3 | G | 1 |
| 3 | H | 2 |
| 3 | I | 3 |
+-------+------+-----+
To learn how to create the sets, have a look at this question/answer.
Then its a simple
ORDER BY tmp, group, name
You can use MySQL variables to do this.
SELECT grp, name, #row:=#row+1 from table, (SELECT #row:=0) r ORDER BY (#row % 3);
+------+------+--------------+
| grp | name | #row:=#row+1 |
+------+------+--------------+
| 1 | A | 1 |
| 2 | D | 4 |
| 3 | G | 7 |
| 1 | B | 2 |
| 2 | E | 5 |
| 3 | H | 8 |
| 1 | C | 3 |
| 2 | F | 6 |
| 3 | I | 9 |
+------+------+--------------+