简体   繁体   中英

SQL - Filter rows by attributes

I have 3 tables USERS, WORKFLOWS, ATTRIBUTES. WORKFLOWS tables values will be NEW, UPDATE and DELETE and ATTRIBUTES table contains workflow attributes like comment, doneBy, dateOfDone etc there are many. Users and Workflows table are connected by USR_ID and workflows and Attributes are connected by WF_ID.

+--------+------------+------------+    +--------+---------+------------+
|USR_ID  | USR_NAME   | IS_GENUINE |    |WF_ID   | WF_NAME | USR_ID     |
+--------|------------+------------+    +--------|---------+------------+
| 1      |  John      |   Y        |    | 1      |  NEW    |   1        |
| 2      |  King      |   Y        |    | 2      |  Update |   1        |
| 3      |  Mark      |   N        |    | 3      |  Delete |   1        |
| 4      |  Smith     |   N        |    | 4      |  Delete |   2        |
| 5      |  Zack      |   Y        |    | 5      |  Update |   2        |
+---------------------+------------+    | 6      |  New    |   3        |
                                        | 7      |  Update |   5        |
                                        +------------------+------------+
+--------+--------------+----------------+-------+
|ATTR_ID | ATTR_NAME   | ATTR_VALUE      | WF_ID |
+--------|------------- +----------------+-------+
| 1      |  comment     |   good         |  1    |
| 2      |  doneBy      |   suresh       |  1    |
| 3      |  comment     |   good         |  2    |
| 4      |  doneBy      |   suresh       |  2    |
| 5      |  comment     |   bad          |  3    |
| 6      |  doneBy      |   Raj          |  3    |
| 7      |  comment     |   Wow          |  4    |
| 8      |  doneBy      |   Amit         |  4    |
| 9      |  comment     |   good         |  7    |
| 10     |  doneBy      |   suresh       |  7    |
+-----------------------+----------------+-------+

Now comes the major question I want to fetch the user info along with workflows and attributes if the IS_GENUINE = 'y' and comment = 'good' and doneBy = 'suresh'.

Expected Output

+--------+------------+---------+-----------+------------+
|USR_ID  | USR_NAME   | WF_NAME | ATTR_NAME | ATTR_VALUE |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  NEW    |  comment  | good       |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  NEW    |  doneBy   | suresh     |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  UPDATE |  comment  | good       |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  UPDATE |  doneBy   | suresh     |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  DELETE |  comment  | bad        |
+--------|------------+---------+-----------|------------+
| 1      |  John      |  DELETE |  doneBy   | Raj        |
+--------|------------+---------+-----------|------------+
| 5      |  Zack      |  UPDATE |  comment  | good       |
+--------|------------+---------+-----------|------------+
| 5      |  Zack      |  UPDATE |  doneBy   | suresh     |
+--------|------------+---------+-----------|------------+

You can use windows function count as follows:

Select USR_ID, USR_NAME, WF_NAME, ATTR_NAME, ATTR_VALUE from
(Select U.USR_ID, U.USR_NAME, W.WF_NAME, A.ATTR_NAME, A.ATTR_VALUE, 
        count(case when a.attr_name = 'comment' and attr_value = 'good' then 1 end) over (partition by a.wf_id) as comm_cnt,
        count(case when a.attr_name = 'doneBy' and attr_value = 'suresh' then 1 end) over (partition by a.wf_id) as suresh_cnt
from
Users u join workflow w
On u.user_id = w.user_id
Join attributes a on a.wf_id = w.wf_id
Where is_genuine = 'Y')
Where comm_cnt = 1 and suresh_cnt = 1;

Try this one:

SELECT user_id, usr_name, wf_name, attr_name, attr_value
FROM users AS u JOIN attributes AS a ON u.user_id = a.user_id , workflows
    JOIN attr_value ON b.wf_id = c.wf_id
WHERE is_genuine = 'y' AND
    (attr_name = 'comment' AND attr_value = 'good') OR
    (attr_name = 'doneBy' AND attr_value = 'suresh');

PS I would restructure ATTRIBUTES . Try this:

+--------+---------+----------+-------+
|ATTR_ID | COMMENT | BY       | WF_ID |
+--------|---------+----------+-------+
| 1      |  good   |  suresh  |  1    |
| 2      |  good   |  suresh  |  2    |
| 3      |  bad    |  Raj     |  3    |
| 4      |  Wow    |  Amit    |  4    |
| 5      |  good   |  suresh  |  7    |
+------------------+----------+-------+

Then the query can look like this:

SELECT user_id, usr_name, wf_name, attr_name, attr_value
FROM users AS u JOIN attributes AS a ON u.user_id = a.user_id , workflows
    JOIN attr_value ON b.wf_id = c.wf_id
WHERE is_genuine = 'y' AND
    (comment = 'good' AND by = 'suresh');

Results will look like this:

+---------+----------+---------+---------+--------+
| usr_id  | usr_name | wf_name | comment | by     |
+---------|----------+---------+---------|--------+
|  1      |  John    |  new    |  good   | suresh |
|  1      |  John    |  update |  good   | suresh |
|  1      |  John    |  delete |  bad    | Raj    |
|  5      |  Zack    |  update |  good   | suresh |
+---------|----------+---------+---------|--------+

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM