MySQL conditional row update based on other tables - mysql

I have the following MySQL tables:
CREATE TABLE notification
(`id` int, `person_id` int, `rule_id` int, `account_id` int, `account_display_name` varchar(16))
;
INSERT INTO notification
(`id`, `person_id`, `rule_id`, `account_id`, `account_display_name`)
VALUES
(1, 1, 1, 1, 'Muad''Dib'),
(2, 1, 1, 2, 'Kwisatz Haderach'),
(3, 1, 2, 2, 'Kwisatz Haderach'),
(4, 2, 1, 3, 'Duncan'),
(5, 2, 2, 4, 'Duncan Idaho')
;
CREATE TABLE person
(`id` int, `name` varchar(6), `organization_id` int)
;
INSERT INTO person
(`id`, `name`, `organization_id`)
VALUES
(1, 'paul', 1),
(2, 'duncan', 1),
(3, 'paul', 2),
(4, 'duncan', 2),
(5, 'paul', 3),
(6, 'duncan', 3)
;
CREATE TABLE account
(`id` int, `display_name` varchar(16), `person_id` int)
;
INSERT INTO account
(`id`, `display_name`, `person_id`)
VALUES
(1, 'Muad''Dib', 1),
(2, 'Kwisatz Haderach', 1),
(3, 'Duncan', 2),
(4, 'Duncan Idaho', 2),
(5, 'Muad''Dib', 3),
(6, 'Kwisatz Haderach', 3),
(7, 'Duncan', 4),
(8, 'Duncan Idaho', 4),
(9, 'Muad''Dib', 5),
(10, 'Kwisatz Haderach', 5),
(11, 'Duncan', 6),
(12, 'Duncan Idaho', 6)
;
CREATE TABLE organization
(`id` int, `name` varchar(17))
;
INSERT INTO organization
(`id`, `name`)
VALUES
(1, 'atreides'),
(2, 'atreides_dev'),
(3, 'atreides_research')
;
CREATE TABLE rule
(`id` int, `name` varchar(14))
;
INSERT INTO rule
(`id`, `name`)
VALUES
(1, 'bug'),
(2, 'false_positive')
;
Conceptually, the system in question generates a notification when an event occurs that is considered relevant to person. Whether or not a notification gets generated is determined by rule (the relation between person and rule is defined elsewhere, but that's outside the scope of this question). Every notification that gets generated for a person is specifically related to an account owned by that person, and it also contains the (denormalized) account_display_name of the account.
Notice that a person is also related to exactly one organization.
Currently, I have a set of notifications (with related accounts) for multiple persons in a particular organization. But I need to move these notifications to different replica organizations (with replica persons and accounts) based on the rule that caused the notification.
Below is an example of the type of migration I'm trying to perform.
State of related tables
person
+----+--------+-----------------+
| id | name | organization_id |
+----+--------+-----------------+
| 1 | paul | 1 |
| 2 | duncan | 1 |
| 3 | paul | 2 |
| 4 | duncan | 2 |
| 5 | paul | 3 |
| 6 | duncan | 3 |
+----+--------+-----------------+
organization
+----+-------------------+
| id | name |
+----+-------------------+
| 1 | atreides |
| 2 | atreides_dev |
| 3 | atreides_research |
+----+-------------------+
account
+----+------------------+-----------+
| id | display_name | person_id |
+----+------------------+-----------+
| 1 | Muad'Dib | 1 |
| 2 | Kwisatz Haderach | 1 |
| 3 | Duncan | 2 |
| 4 | Duncan Idaho | 2 |
| 5 | Muad'Dib | 3 |
| 6 | Kwisatz Haderach | 3 |
| 7 | Duncan | 4 |
| 8 | Duncan Idaho | 4 |
| 9 | Muad'Dib | 5 |
| 10 | Kwisatz Haderach | 5 |
| 11 | Duncan | 6 |
| 12 | Duncan Idaho | 6 |
+----+------------------+-----------+
rule
+----+----------------+
| id | name |
+----+----------------+
| 1 | bug |
| 2 | false_positive |
+----+----------------+
Initial state of notifications
+----+-----------+---------+------------+----------------------+
| id | person_id | rule_id | account_id | account_display_name |
+----+-----------+---------+------------+----------------------+
| 1 | 1 | 1 | 1 | Muad'Dib |
| 2 | 1 | 1 | 2 | Kwisatz Haderach |
| 3 | 1 | 2 | 2 | Kwisatz Haderach |
| 4 | 2 | 1 | 3 | Duncan |
| 5 | 2 | 2 | 4 | Duncan Idaho |
+----+-----------+---------+------------+----------------------+
End state of notifications
+----+-----------+---------+------------+----------------------+
| id | person_id | rule_id | account_id | account_display_name |
+----+-----------+---------+------------+----------------------+
| 1 | 3 | 1 | 5 | Muad'Dib |
| 2 | 3 | 1 | 6 | Kwisatz Haderach |
| 3 | 5 | 2 | 10 | Kwisatz Haderach |
| 4 | 4 | 1 | 7 | Duncan |
| 5 | 6 | 2 | 12 | Duncan Idaho |
+----+-----------+---------+------------+----------------------+
As you can see, the person_id and account_id of the notifications have been updated based on the notification's rule_id. Specifically:
Every notification generated by the bug rule (ID 1) was moved to the corresponding person and account replicas in the atreides_dev organization (ID 2).
Every notification generated by the false_positive rule (ID 2) was moved to the corresponding person and account replicas in the atreides_research organization (ID 3).
I've written a SQL query that (I believe) selects the correct notification.person_id and notification.account_id based on notification.rule_id, but I'm unsure of the best way to use this in an UPDATE statement, such that every notification gets updated correctly.
Here is the SELECT:
select p_replica.id, acc_replica.id as account_id
from (select p.name, person_id, rule_id, account_id, account_display_name from notification n
inner join person p
on n.person_id = p.id
where p.organization_id = 1
and n.rule_id in (1)) as notifications
inner join person p_replica
on p_replica.name = notifications.name
and p_replica.organization_id = 2
inner join account acc_replica
on acc_replica.person_id = p_replica.id
and acc_replica.display_name = notifications.account_display_name;
Notice that the SELECT specifies an origin organization (ID 1), a destination organization (ID 2), and a rule whose notifications need to be migrated. Recall that this is based on a mapping of rule to destination organization. In other words, selecting all updated notifications would require one execution of this query per mapping of rule -> organization.
What would an UPDATE query for performing this migration look like?
Here is a SQL Fiddle to play around with.

Related

How to create MySQL histogram type buckets based on column value

I have the following table and I am trying to create histogram style buckets through MySQL.
| Id | Values |
| -------- | --------- |
| 1 | 5 |
| 2 | 7 |
| 3 | 9 |
| 4 | 11 |
| 5 | 15 |
| 6 | 31 |
| 7 | 32 |
| 8 | 43 |
What I am trying to achieve is as following:
| bucket | count |
| -------- | --------- |
| 0-9 | 3 |
| 10-19 | 2 |
| 20-29 | 0 |
| 30-39 | 2 |
| 40-49 | 1 |
Does anyone know how we can get this in a clean way?
One possible way is to create a reference table for the bucket list then LEFT JOIN it with your table. Try the following steps.
Create a table bucket_list for example:
CREATE TABLE bucket_list (
id INT NOT NULL AUTO_INCREMENT,
startno INT,
endno INT,
PRIMARY KEY(id));
Insert values into bucket_list:
INSERT INTO bucket_list (startno, endno)
VALUES
(0, 9),
(10, 19),
(20, 29),
(30, 39),
(40, 49),
(50, 59),
(60, 69),
(70, 79);
Create a query to return expected result:
SELECT CONCAT(a.startno,'-',a.endno) AS bucket,
SUM(CASE WHEN b.val IS NULL THEN 0 ELSE 1 END) AS COUNT
FROM bucket_list a
LEFT JOIN mytable b ON b.val BETWEEN a.startno AND a.endno
GROUP BY bucket;
Here's a fiddle: https://dbfiddle.uk/?rdbms=mysql_8.0&fiddle=7fee426efa2b1f1e39377bb7beb68b62

How to sum the values of column on duplicate key?

I have a table like this:
// mytable
+----+--------+-------+-------+
| id | name | key | value |
+----+--------+-------+-------+
| 1 | jack | 1 | 10 |
| 2 | peter | 1 | 5 |
| 3 | jack | 2 | 5 |
| 4 | ali | 1 | 2 |
| 5 | jack | 1 | 5 |
| 6 | jack | 1 | 10 |
| 7 | bert | 4 | 2 |
| 8 | peter | 2 | 10 |
| 9 | bert | 4 | 5 |
+----+--------+-------+-------+
Now I want to sum the numbers of value where both name and key are identical. So, I want this output:
// mynewtable
+----+--------+-------+-------+
| id | name | key | value |
+----+--------+-------+-------+
| 1 | jack | 1 | 25 |
| 2 | peter | 1 | 5 |
| 3 | jack | 2 | 5 |
| 4 | ali | 1 | 2 |
| 7 | bert | 4 | 7 |
| 8 | peter | 2 | 10 |
+----+--------+-------+-------+
Is it possible to I do that?
Edit: How can I do that for insert?
// mytable
+----+--------+-------+-------+
| id | name | key | value |
+----+--------+-------+-------+
| 1 | jack | 1 | 25 |
| 2 | peter | 1 | 5 |
| 3 | jack | 2 | 5 |
| 4 | ali | 1 | 2 |
| 7 | bert | 4 | 7 |
| 8 | peter | 2 | 10 |
+----+--------+-------+-------+
Inserting these rows:
+----+--------+-------+-------+
| 10 | jack | 1 | 5 |
+----+--------+-------+-------+
+----+--------+-------+-------+
| 11 | bert | 1 | 2 |
+----+--------+-------+-------+
What I want: (output)
// mynewtable
+----+--------+-------+-------+
| id | name | key | value |
+----+--------+-------+-------+
| 1 | jack | 1 | 30 |
| 2 | peter | 1 | 5 |
| 3 | jack | 2 | 5 |
| 4 | ali | 1 | 2 |
| 7 | bert | 4 | 7 |
| 8 | peter | 2 | 10 |
| 11 | bert | 1 | 2 |
+----+--------+-------+-------+
You have to group by more columns.
select name, key, sum(value) from mytable group by name, key;
Group by name, key
select name, key, sum(value) as value
from mytable group by name,key
check this
CREATE TABLE #testing_123
([id] int, [name] varchar(5), [key] int, [value] int)
;
INSERT INTO #testing_123
([id], [name], [key], [value])
VALUES
(1, 'jack', 1, 10),
(2, 'peter', 1, 5),
(3, 'jack', 2, 5),
(4, 'ali', 1, 2),
(5, 'jack', 1, 5),
(6, 'jack', 1, 10),
(7, 'bert', 4, 2),
(8, 'peter', 2, 10),
(9, 'bert', 4, 5)
;
query used was
select min(id) id ,name,[key],sum(value) value from #testing_123 group by name,[key] order by 1
output after insert
For the first part (to get the id column in the way requested), you could work along:
INSERT INTO mynewtable
(id, name, `key`, `value`)
SELECT
MIN(id), name, `key`, SUM(`value`)
FROM mytable
GROUP BY name, `key`
;
Now, provided mynewtable is defined with a unique index on name and key like
CREATE TABLE mynewtable
(id INT, name VARCHAR(5), `key` INT, `value` INT, UNIQUE (name, `key`));
you'd get the requested result with
INSERT INTO mynewtable
(id, name, `key`, `value`)
VALUES
(10, 'jack', 1, 5),
(11, 'bert', 1, 2)
ON DUPLICATE KEY UPDATE `value` = `value` + VALUES(`value`)
;
Beware:
It requires the unique index on name and key to work.
It might not work correctly, if there are other unique indexes and/or a primary key on the same table as well.
NB:
Please try to avoid the use of reserved words such as value and key for, e.g., column names.

How to query multiple tables using a single query?

I want my tables to output something like this
---------------------------------------------------------------------------------------------
| date | location | time | delegate 1 | delegate 2 |
|--------------------------------------------------------------------------------------------
| 2015-12-07 | Table 1 | 9:00 | first_name_4 last_name_4 | first_name_5 last_name_5 |
|--------------------------------------------------------------------------------------------
| | 9:30 | first_name_4 last_name_4 | first_name_6 last_name_6 |
|--------------------------------------------------------------------------------------------
| | 9:30 | first_name_3 last_name_3 | first_name_7 last_name_7 |
|--------------------------------------------------------------------------------------------
| | 9:00 | first_name_3 last_name_3 | first_name_7 last_name_7 |
|--------------------------------------------------------------------------------------------
Here are the tables on my db
meetings table
-------------------------------------------------------------------------------------------------
| id | date_id | time_id | location_id | delegate_id_1 | delegate_id_2 | status |
|------------------------------------------------------------------------------------------------
| 1 | 1 | 1 | 1 | 4 | 5 | A |
|------------------------------------------------------------------------------------------------
| 2 | 1 | 2 | 1 | 4 | 6 | A |
|------------------------------------------------------------------------------------------------
| 3 | 1 | 1 | 1 | 2 | 6 | P |
|------------------------------------------------------------------------------------------------
| 4 | 1 | 2 | 1 | 1 | 3 | A |
|------------------------------------------------------------------------------------------------
| 5 | 1 | 1 | 1 | 1 | 3 | A |
|------------------------------------------------------------------------------------------------
users table
-----------------------------------------
| id | first_name | last_name |
|----------------------------------------
| 1 | first_name_1 | last_name_1 |
|----------------------------------------
| 2 | first_name_2 | last_name_2 |
|----------------------------------------
| 3 | first_name_3 | last_name_3 |
|----------------------------------------
| 4 | first_name_4 | last_name_4 |
|----------------------------------------
| 5 | first_name_5 | last_name_5 |
|----------------------------------------
| 6 | first_name_6 | last_name_6 |
|----------------------------------------
locations table
-----------------------------
| id | location_name |
|----------------------------
| 1 | Table 1 |
|----------------------------
time table
-------------------------
| id | meeting_time |
|------------------------
| 1 | 9:00:00 |
|------------------------
| 1 | 9:30:00 |
|------------------------
dates table
-------------------------
| id | meeting_date |
|------------------------
| 1 | 2015-12-07 |
|------------------------
| 2 | 2015-12-08 |
|------------------------
| 3 | 2015-12-09 |
|------------------------
My initial query goes like this
-- $query_date
SELECT meeting_date
FROM dates
WHERE meeting_date = '2015-12-07'
-- $query_location
SELECT location_name.location
from location
LEFT JOIN meetings
ON meetings.location_id=location.id
LEFT JOIN date
ON meetings.date_id=date.id
WHERE meeting_date.dates = '2015-12-07'
Now, here's the part where I got it wrong.
-- $query_final
SELECT meeting_time.time, delegate1.first_name AS first_name_1,
delegate1.last_name AS last_name_1, delegate2.first_name AS first_name_2,
delegate2.last_name AS last_name_2
FROM meetings
INNER JOIN users delegate1
ON meetings.delegate_id_1=users.id
LEFT JOIN users delegate2
ON meetings.delegate_id_2=users.id
WHERE meetings.status='A'
The results on my last query give me unexpected results since the results show more entries than my meetings table.
I know the queries I made are costly but I don't know how to make a more optimized query. I don't even know if it's possible to get the results into a single query only. Any help well do. Thanks.
You can bring back everything with a single query with the right JOIN.
Be Careful, when you use column name on SQL, the syntax is TABLE.COLUMN_NAME, it seem you mistake on the order quit often...
I changed some table name as you sometime use an s at the end and sometime no.
As time and date are SQL keyword, it's better with s everywhere
SQL Fiddle
MySQL 5.6 Schema Setup:
CREATE TABLE meetings (`id` int, `date_id` int, `time_id` int, `location_id` int, `delegate_id_1` int, `delegate_id_2` int, `status` varchar(1));
INSERT INTO meetings (`id`, `date_id`, `time_id`, `location_id`, `delegate_id_1`, `delegate_id_2`, `status`)
VALUES (1, 1, 1, 1, 4, 5, 'A'),
(2, 1, 2, 1, 4, 6, 'A'),
(3, 1, 1, 1, 2, 6, 'P'),
(4, 1, 2, 1, 1, 3, 'A'),
(5, 1, 1, 1, 1, 3, 'A');
CREATE TABLE users (`id` int, `first_name` varchar(12), `last_name` varchar(11));
INSERT INTO users (`id`, `first_name`, `last_name`)
VALUES (1, 'first_name_1', 'last_name_1'),
(2, 'first_name_2', 'last_name_2'),
(3, 'first_name_3', 'last_name_3'),
(4, 'first_name_4', 'last_name_4'),
(5, 'first_name_5', 'last_name_5'),
(6, 'first_name_6', 'last_name_6');
CREATE TABLE locations (`id` int, `location_name` varchar(7));
INSERT INTO locations (`id`, `location_name`)
VALUES (1, 'Table 1');
CREATE TABLE times (`id` int, `meeting_time` varchar(7));
INSERT INTO times (`id`, `meeting_time`)
VALUES (1, '9:00:00'),
(2, '9:30:00') ;
CREATE TABLE dates (`id` int, `meeting_date` varchar(10)) ;
INSERT INTO dates (`id`, `meeting_date`)
VALUES (1, '2015-12-07'),
(2, '2015-12-08'),
(3, '2015-12-09') ;
Query 1:
-- $query_final
SELECT locations.location_name,
`times`.meeting_time,
delegate1.first_name AS first_name_1,
delegate1.last_name AS last_name_1,
delegate2.first_name AS first_name_2,
delegate2.last_name AS last_name_2
FROM meetings
LEFT JOIN locations
ON meetings.location_id=locations.id
LEFT JOIN dates
ON meetings.date_id=`dates`.id
LEFT JOIN times
ON meetings.time_id=`times`.id
INNER JOIN users delegate1
ON meetings.delegate_id_1 = delegate1.id
LEFT JOIN users delegate2
ON meetings.delegate_id_2 = delegate2.id
WHERE
meetings.status = 'A'
AND dates.meeting_date = '2015-12-07'
Results:
| location_name | meeting_time | first_name | last_name | first_name | last_name |
|---------------|--------------|--------------|-------------|--------------|-------------|
| Table 1 | 9:00:00 | first_name_1 | last_name_1 | first_name_3 | last_name_3 |
| Table 1 | 9:30:00 | first_name_1 | last_name_1 | first_name_3 | last_name_3 |
| Table 1 | 9:00:00 | first_name_4 | last_name_4 | first_name_5 | last_name_5 |
| Table 1 | 9:30:00 | first_name_4 | last_name_4 | first_name_6 | last_name_6 |

MySQL subquery/complex query question, tracking state changes

I have a table that tracks contact class state changes by date. The question that I am trying to answer is what is the current state of all contacts on a certain date.
DROP TABLE IF EXISTS `contact_class_state`;
CREATE TABLE `contact_class_state` (
`id` int unsigned NOT NULL AUTO_INCREMENT,
`contact_id` int unsigned DEFAULT NULL, -- the contact
`contact_class` int unsigned,
`state_date` date,
PRIMARY KEY (`id`),
INDEX (`contact_id`)
) DEFAULT CHARSET=utf8;
INSERT INTO `contact_class_state` (`contact_id`, `contact_class`, `state_date`) VALUES
(1, 1, '2011-01-01'),
(2, 1, '2011-01-01'),
(3, 1, '2011-01-01'),
(4, 1, '2011-01-01'),
(5, 1, '2011-01-01'),
(1, 2, '2011-02-01'),
(3, 2, '2011-02-01'),
(5, 2, '2011-02-01'),
(1, 1, '2011-02-15'),
(5, 3, '2011-03-01');
For example, the following query:
SELECT contact_id, contact_class, state_date
FROM contact_class_state
WHERE state_date <= '2011-02-27'
ORDER BY contact_id, state_date DESC
returns
+------------+---------------+------------+
| contact_id | contact_class | state_date |
+------------+---------------+------------+
| 1 | 1 | 2011-02-15 |
| 1 | 2 | 2011-02-01 |
| 1 | 1 | 2011-01-01 |
| 2 | 1 | 2011-01-01 |
| 3 | 2 | 2011-02-01 |
| 3 | 1 | 2011-01-01 |
| 4 | 1 | 2011-01-01 |
| 5 | 2 | 2011-02-01 |
| 5 | 1 | 2011-01-01 |
+------------+---------------+------------+
While this is technically correct, I only need the first (or last if sorted ASC) row for each contact_id as the latest date will always give me current state of the contact, per the below:
+------------+---------------+------------+
| contact_id | contact_class | state_date |
+------------+---------------+------------+
| 1 | 1 | 2011-02-15 |
| 2 | 1 | 2011-01-01 |
| 3 | 2 | 2011-02-01 |
| 4 | 1 | 2011-01-01 |
| 5 | 2 | 2011-02-01 |
+------------+---------------+------------+
I am pretty sure a sub or a complex query would do the trick but I am having a mental block with the SQL. I am also open to other approaches to solve this issue.
Thanks!
If your query is in fact what you want (except then grouped by contact_id), then do exactly that.
SELECT * FROM
(SELECT contact_id, contact_class, state_date
FROM contact_class_state
WHERE state_date <= '2011-02-27'
ORDER BY contact_id, state_date DESC) table1
GROUP BY contact_id
This is tested and works perfect.

Grouping MySQL data

I have this table, lets call it table one.
+----+---------+-----------------+
| id | link_id | url |
+----+---------+-----------------+
| 1 | 1 | www.example.com |
| 2 | 1 | www.abc.com |
| 3 | 1 | www.test.com |
| 4 | 1 | www.t1.com |
| 5 | 1 | www.newtest.com |
| 6 | 1 | www.testing.com |
| 7 | 1 | www.abc.com |
| 8 | 1 | www.example.com |
| 9 | 1 | www.web1.com |
| 10 | 1 | www.web2.com |
| 11 | 2 | www.dear.com |
| 12 | 2 | www.google.com |
| 13 | 2 | www.flowers.com |
| 14 | 2 | www.yahoo.com |
| 15 | 2 | www.abc.com |
| 16 | 2 | www.dell.com |
| 17 | 2 | www.web.com |
| 18 | 2 | www.example.com |
| 19 | 2 | www.test.com |
| 20 | 2 | www.abc.com |
+----+---------+-----------------+
20 rows in set (0.00 sec)
The link_id is sort the primary identifier in the table. It tells me which urls appear in link 1, link 2 , etc.
What I want to acomplish is:
1. Get all the unique URLs,
2. Show which links the URL belongs to
So an example output would be:
+-----------------+---------+
| url | link_id |
+-----------------+---------+
| www.example.com | 1 |
| www.example.com | 2 |
| www.abc.com | 1 |
| www.abc.com | 2 |
| www.test.com | 1 |
| www.test.com | 2 |
| www.t1.com | 1 |
| www.newtest.com | 1 |
| www.testing.com | 1 |
| www.web1.com | 1 |
...and so on.
So you can see that www.example.com appears twice since it is associated with both links 1 and 2, but web1.com appears only once since it belongs only to link 1.
I have tried several different group by but I only end up scratching my head even more.
Any help is appreciated. Here is the table dump if anyone needs:
CREATE TABLE IF NOT EXISTS `table1` (
`id` int(11) unsigned NOT NULL AUTO_INCREMENT,
`link_id` tinyint(3) unsigned DEFAULT NULL,
`url` varchar(255) COLLATE utf8_unicode_ci DEFAULT NULL,
PRIMARY KEY (`id`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8 COLLATE=utf8_unicode_ci AUTO_INCREMENT=21 ;
INSERT INTO `table1` (`id`, `link_id`, `url`) VALUES
(1, 1, 'www.example.com'),
(2, 1, 'www.abc.com'),
(3, 1, 'www.test.com'),
(4, 1, 'www.t1.com'),
(5, 1, 'www.newtest.com'),
(6, 1, 'www.testing.com'),
(7, 1, 'www.abc.com'),
(8, 1, 'www.example.com'),
(9, 1, 'www.web1.com'),
(10, 1, 'www.web2.com'),
(11, 2, 'www.dear.com'),
(12, 2, 'www.google.com'),
(13, 2, 'www.flowers.com'),
(14, 2, 'www.yahoo.com'),
(15, 2, 'www.abc.com'),
(16, 2, 'www.dell.com'),
(17, 2, 'www.web.com'),
(18, 2, 'www.example.com'),
(19, 2, 'www.test.com'),
(20, 2, 'www.abc.com');
Wouldn't a DISTINCT list work? Does order matter?
SELECT DISTINCT url, link_id
FROM `table1`
ORDER BY 1, 2
Unless I'm misunderstanding the question, it sounds like all you need is a DISTINCT clause:
select distinct url, link_id from table1;
SELECT url, GROUP_CONCAT(link_id)
FROM table1
GROUP
BY url;
That'll give you all the distinct URLs, each with a list of link ids
Select url, link_id
From Table1
Group By url, link_id
select * from table group by link_id,url
Well imho you should group by both link_id and url, and than maybe sort by url so the same urls are together.
SELECT url, link_id FROM table1
ORDER BY url
GROUP BY url, link_id
Unless I'm missing something:
SELECT DISTINCT url, link_id FROM table1;