سؤال

In order to conserve space and eliminate duplicates, I have the following table of distances between locations:

patientIDa | patientIDb | distance |  
1          | 2          | 4.5      |  
1          | 3          | 2.8      |  
1          | 4          | 1.3      |  
1          | 5          | 0.9      |  
2          | 3          | 2.0      |  
2          | 4          | 5.3      |  
2          | 5          | 4.4      |  
3          | 4          | 4.4      |  
3          | 5          | 3.7      |  
4          | 5          | 4.5      |  

I run the following query to get the three closest distances to patient #3:

Select * From Distances Where (patientIDa=3 OR patientIDb=3)
Order By distance
Limit 3;

Result set:

patientIDa  patientIDb  distance  
2           | 3         | 2.0  
1           | 3         | 2.8  
3           | 5         | 3.7  

How would I go about extracting the corresponding patientIDx's (2, 1, 5), as they are in different columns? Running MySQL 5.6 on aws. Apologies on the formatting.

As an aside, is this bad design to begin with? I'm fairly new at DB tech.

هل كانت مفيدة؟

المحلول

    SELECT patientIDa, patientIDb, distance 
    FROM Distances 
    WHERE patientIDa=3 
UNION ALL
    SELECT patientIDb, patientIDa, distance  
    FROM Distances 
    WHERE patientIDb=3
ORDER BY distance
LIMIT 3;

نصائح أخرى

And if you want to avoid a UNION - not certain of performance here, but this might be better (see fiddle here) - you don't have to query the table twice as for @Akina's query! You might want to check with a large dataset.

Create and populate table:

CREATE table pat_dis
(
  p1  INT,
  p2  INT,
  dis FLOAT
);

INSERT INTO pat_dis VALUES
( 1, 2, 1.1),
( 1, 5, 1.5),
( 2, 3, 2.0),  
( 1, 3, 2.8),
( 3, 5, 3.7),
( 8, 3, 9.9),
( 4, 7, 0.1); -- << extra record no paitent 3 and small distance

And then run this query:

SELECT 
  CASE 
     WHEN LEAST(p1, p2) < 3 THEN p1
     WHEN GREATEST (p1, p2 > 3) THEN  p2
  END AS patient,
  dis AS distance
FROM pat_dis
WHERE (p1 = 3 OR p2 = 3)
ORDER BY distance
LIMIT 3;

Result:

patient     distance
      2            2
      1          2.8
      5          3.7

Et voilà! Following the OP's comment on my elementary error, with the new WHERE clause, this is now the correct answer even if there are patients with a shorter distance between them but neither of whom is patient 3. Both fiddles have been amended.

As an aside, I would recommend that you upgrade to version 8 of MySQL. Apart from all sorts of goodies like Common Table Expressions and Window functions, you get CHECK constraints which allow you to write this (see fiddle here):

CREATE table pat_dis
(
  p1  INT,
  p2  INT, 
  CONSTRAINT patient_not_same CHECK (p1 != p2),  -- version 8 - new line!
  dis FLOAT
);

Now try:

INSERT INTO pat_dis VALUES (3, 3, 3.6); -- cannot insert identical patients!
                                        -- see same line in 1st fiddle.

Result:

Check constraint 'patient_not_same' is violated.
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى dba.stackexchange
scroll top