2

I'm a beginner of sql. I have a question about selecting specific row values.

Here's the data

| KEY  | LOCATION | IDX  |
| ---- | -------- | ---- |
| 01   | 1-01     | 0    |
| 01   | 1-02     | 1    |
| 01   | 1-03     | 2    |
| 02   | null     | 0    |
| 02   | 2-02     | 1    |
| 02   | 2-03     | 2    |
| 03   | null     | 0    |
| 03   | null     | 1    |
| 03   | null     | 2    |

and what am I expected:

| KEY  | LOCATION | IDX  |
| ---- | -------- | ---- |
| 01   | 1-01     | 0    |
| 02   | 2-02     | 1    |
| 03   | null     | 1    |

for the same KEY, I want to get the value which IDX=0 and LOCATION is not null, and if not, return the value which IDX=1;

Is there any way to do that? I'm using sqlite3.

Appreciate the help!

4 Answers 4

1

I'd do it like this:

SELECT
  z.key,
  CASE WHEN z.location is not null 
    THEN z.location
    ELSE o.location
  END as location,
  CASE WHEN z.location is not null 
    THEN z.idx
    ELSE o.idx
  END as idx
FROM
(SELECT * FROM t WHERE idx=0) z
  INNER JOIN
  (SELECT * FROM t WHERE idx=1) o
  ON z.key = o.key
Sign up to request clarification or add additional context in comments.

Comments

1

You can use union all with not in

with tab( KEY, LOCATION, IDX ) as
(
 select '01','1-01', 0 union all   
 select '01','1-02', 1 union all   
 select '01','1-03', 2 union all   
 select '02', null , 0 union all   
 select '02','2-02', 1 union all   
 select '02','2-03', 2 union all   
 select '03', null , 0 union all   
 select '03', null , 1 union all   
 select '03', null , 2      
)
select * from tab where location is not null and idx =0 
union all
select * from tab t where idx =1
                    and key not in
        ( select key 
            from tab 
           where location is not null and idx =0
        ) 

 key   location idx
----   -------- ---
 01     1-01     0
 02     2-02     1
 03     NULL     1

Rextester Demo

Comments

1

This is a tricky problem because you are looking at relationships between different rows. This solution is similar to Barbaros's. However, SQLite supports CTEs, so I prefer to express this as:

with l0 as (
      select t.* 
      from t
      where t.location is not null and t.idx = 0
     )
select l0.*
from l0
union all
select t.*
from t
where idx = 1 and
      not exists (select 1 from l0 where l0.key = l1.key);

That is, take everything from l0 -- the ones with idx = 0 that meet your conditions. Then take the idx = 1 for additional keys that do not meet that condition.

Comments

1

First, get only those rows that might be useful:

SELECT *
FROM t
WHERE (idx = 0 AND location IS NOT NULL)
   OR  idx = 1;
key         location    idx       
----------  ----------  ----------
01          1-01        0         
01          1-02        1         
02          2-02        1         
03                      1         

Then use grouping to return only one row per key. If there are two table rows, you want the one with the smaller idx, so use MIN() to select it:

SELECT key, location, MIN(idx) AS idx
FROM t
WHERE (idx = 0 AND location IS NOT NULL)
   OR  idx = 1
GROUP BY key;
key         location    idx       
----------  ----------  ----------
01          1-01        0         
02          2-02        1         
03                      1         

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.