1

Im a lil bit stuck here, really hope somebody could help me out. I couldn't found yet the answer from google.

Ok let say the data is like below:

TableName=> Events

| Node_Name| Status    |
+----------+-----------+
| Node_1   | Completed |
| Node_1   | Completed |
| Node_2   | Failed    |
| Node_2   | Completed |
| Node_3   | Failed    |
| Node_3   | Failed    |

Query:

select node_name, count(*)
from events
where status='Failed'
group by node_name

Result:

| Node_2 | 1 |
| Node_3 | 2 |

The question is, how can i group a node_name that never "failed" and always completed.

Query: ?????????

Result that I wanted:

=>Node_1

Really appreciate your help.

Thank you!

Gordon Linoff
  • 1,242,037
  • 58
  • 646
  • 786
Tommy
  • 23
  • 1
  • 3
  • 1
    What DB engine do you really use? – juergen d Jun 12 '15 at 20:10
  • 1
    Which DBMS are you using? mysql <> sql server <> db2 – Sean Lange Jun 12 '15 at 20:10
  • There are a number of ways to do this....MAX(Status) = 'Completed', Where NOT EXISTS, It depends a bit on which dbms you are using and what your tables actually look like. – Sean Lange Jun 12 '15 at 20:12
  • You're dealing with a relational database, so start thinking in terms of SETS of data. so it'd be (basically) a two part query. get the set of records that have failed, then get the equivalent set which DON'T exist in the failed set. – Marc B Jun 12 '15 at 20:13
  • are there still tags for dBase II ? – Drew Jun 12 '15 at 20:15
  • you need nested query – mussdroid Jun 12 '15 at 20:41
  • I removed the extraneous database tags. @Tommy . . . Feel free to add one (or two) tags that describe the database you are really using. – Gordon Linoff Jun 12 '15 at 21:08
  • it's been a few days since you gave any feedback on any of the solutions offered, did any of them manage to solve your problem, and if so which one? – JoshGivens Jun 17 '15 at 04:23
  • The dbms is IBM DB2. Sorry for late reply as i didnt expect to get this overwhelming response. – Tommy Jun 19 '15 at 07:19
  • Im using IBM DB2 for Tivoli Storage Manager (TSM). Apologize for the late reply. I didnt expect to get this fast n overwhelming reply from all of you as this is my first post. There are few solution that is working like what i wanted. Thank you guys for your time. I appreciate it. – Tommy Jun 19 '15 at 07:20

9 Answers9

3

In SQL Server, the EXCEPT operator can do this.

select node_name 
from events 
group by node_name

EXCEPT

select node_name
from events
where status<>'Completed' ;

Explanation: You query all different node names, and you remove all names which are not completed. As a result, only those will stay which are ONLY completed.

SQL Police
  • 4,127
  • 1
  • 25
  • 54
  • fails. you are grouping by, and you have no aggregate usage. this often survives, works, but not in interviews. ooops, sorry, i said `not in` – Drew Jun 12 '15 at 20:30
  • @DrewPierce: Of course you can GROUP without any aggregate function, it's exactly the same as DISTINCT. But it's not needed at all, because MINUS/EXCEPT is always DISTINCT :-) – dnoeth Jun 12 '15 at 20:34
  • i am sorry, i am not worthy, i must now code like this – Drew Jun 12 '15 at 20:35
  • @DrewPierce I don't see the problem. This is a wonderful set operation, set theory at work. I edited it for SQL Server, the operator is called `EXCEPT` there. You can still come for an interview to me ;) – SQL Police Jun 12 '15 at 20:44
  • i just wouldn't use MINUS, it is so negative – Drew Jun 12 '15 at 20:51
  • In SQL server, it is EXCEPT. I changed this. – SQL Police Jun 12 '15 at 20:52
  • @SQLPolice: Why don't you do a pure set based operation without spoiling it with GROUP BY? Btw, it's not SQL Server which calls this operation EXCEPT, it's Standard SQL, the SQLPolice should know that :-) – dnoeth Jun 12 '15 at 20:53
  • onward and upward, you get the support of my minions – Drew Jun 12 '15 at 21:04
  • 1
    This query will fail if [status] is nullable and you have a [node_name] with a null [status]. my second example using CTE works fine however – JamieD77 Jun 12 '15 at 21:12
  • @user1221684: Don't be so nitpicking, this will never happen, the police will never allow a NULL status. – dnoeth Jun 12 '15 at 21:24
  • your answer should be correct as what i wanted. I forgot to mention that im using DB2... thanks anyway! – Tommy Jun 19 '15 at 08:31
1
SELECT
    node_name
FROM
    events
WHERE
    node_name NOT IN (SELECT
                        node_name
                      FROM
                        events
                      WHERE
                        status = 'Failed')
GROUP BY
    node_name

To prevent havoc with missing result sets and jokesters adding Abbracadabra as a status you can use this. Patent Pending

WITH cteAbbracadabra AS
(
    SELECT
        node_name, status, RANK() OVER (PARTITION BY node_name ORDER BY status) rnk
    FROM
        events
    GROUP BY
        node_name, status
)
SELECT  node_name 
FROM    cteAbbracadabra c
WHERE   status = 'Completed'
        AND NOT EXISTS (
            SELECT  * 
            FROM    cteAbbracadabra 
            WHERE   node_name = c.node_name 
                    AND rnk <> c.rnk)
JamieD77
  • 13,796
  • 1
  • 17
  • 27
0

OR with NOT EXISTS...

http://sqlfiddle.com/#!6/60887/4

select Node_Name FROM events WHERE NOT EXISTS
(SELECT 1 FROM events e WHERE e.Node_Name=events.Node_Name AND Status='Failed')
GROUP BY Node_Name
Carsten Massmann
  • 26,510
  • 2
  • 22
  • 43
0

If you're looking for all the statuses in one query, try this (I'm using SQL Server 2014):

SELECT
  [Node_Name],
  SUM(CASE WHEN [Status] = 'Failed' THEN 1 ELSE 0 END) AS Failures
FROM (VALUES 
  ('Node_1', 'Completed'),
  ('Node_1', 'Completed'),
  ('Node_2', 'Failed'),
  ('Node_2', 'Completed'),
  ('Node_3', 'Failed'),
  ('Node_3', 'Failed')
  ) x ([Node_Name], [Status])
GROUP BY [Node_Name]
FilamentUnities
  • 584
  • 5
  • 12
0

To get only the "never failed" nodes:

select node_name
from events
group by node_name
having max(status) = 'Completed'

To get all nodes with a 'Failed' count:

select node_name, 
   sum(case when status = 'Failed' then 1 else 0 end )
from events
group by node_name
dnoeth
  • 59,503
  • 4
  • 39
  • 56
  • Sorry, no. 1st query does not what you expect. Please think again. – SQL Police Jun 12 '15 at 20:26
  • 1
    @SQLPolice: If the maximum status value is 'Completed' there's no 'Failed' status, so why is this wrong? – dnoeth Jun 12 '15 at 20:28
  • Above your statement you write "To get only the "never failed" nodes:" --> What if a node contains 'Abracadabra' ? Who says that you have only 'Completed' and 'Failed'? – SQL Police Jun 12 '15 at 20:32
  • 1
    @SQLPolice: My answer is based on the provided data and works for this. – dnoeth Jun 12 '15 at 20:49
  • oh d don't pull that card :> – Drew Jun 12 '15 at 20:49
  • Your code is still a nasty hack. This like using "goto" in C#. – SQL Police Jun 12 '15 at 20:51
  • @dnoeth . . . This code is reasonable and not a "hack". And, even if it were, it works and answers the OP's question. I've had the same rude response from the same person to one of my questions. – Gordon Linoff Jun 12 '15 at 21:12
  • @GordonLinoff: I know, but I like to get into trouble with police :-) – dnoeth Jun 12 '15 at 21:14
  • You can feel honored at his/her downvote, then. Cheers. – Gordon Linoff Jun 12 '15 at 21:24
  • @dnoeth . . . The answer would be more general with `having min(status) = 'Completed' and max(status) = 'Completed'`, but it is correct (for the OP) as written. – Gordon Linoff Jun 12 '15 at 21:44
  • @GordonLinoff Of course it's okay if something **works**. But do you want to be a "programmer" or a "software architect"? A software architect should aim to write code that is more universal. Otherwise, you need to repeat yourself again and again, and also, your code becomes difficult to maintain. – SQL Police Jun 13 '15 at 09:44
  • @SQLPolice . . . You seem to have a dogmatic and limited understanding of programming (http://stackoverflow.com/questions/6545720/does-anyone-still-use-goto-in-c-sharp-and-if-so-why) and a similarly poor grasp of using SQL in the real world. – Gordon Linoff Jun 13 '15 at 19:32
0

You could create a new column where you can assign a '0' value to completed ones and then everything else to 1. And, then grab only ones where the max() value = 0 (completed only) like this:

SELECT t.node_name
FROM (
    SELECT node_name
        ,STATUS
        ,CASE 
            WHEN STATUS = 'Completed'
                THEN 0
            ELSE 1
            END Completed_Flg
    FROM events
    ) t
GROUP BY t.node_name
HAVING max(t.completed_flg) = 0

SQL Fiddle Demo

FutbolFan
  • 13,235
  • 3
  • 23
  • 35
0
select node_name, count(*)
from events
where count(*) = 
(SELECT count(*) from events where status = 'completed') 
group by node_name; 

that should work, so after doing some testing I found that my original solution didn't work. however I feel like I have now found a working model:

SELECT NODE_NAME, COUNT(*) 
FROM EVENTS 
GROUP BY NODE_NAME 
HAVING(NODE_NAME, COUNT(*)) IN 
(SELECT NODE_NAME, COUNT(*) 
FROM EVENTS WHERE
STATUS = 'completed' GROUP BY NODE_NAME);

so this gets it down to displaying node_1 2. the issue I've run into at this point is being able to drop the count from the end result. I attempted to wrap this into another subquery that I would only pull the node_name from using the in keyword, however because my subqueries thus far each had two operands it won't let me. I'll continue to try to find a finished working model, but this should help to push you in the right direction.

SELECT NODE_NAME FROM(
SELECT NODE_NAME, COUNT(*) 
FROM EVENTS GROUP BY NODE_NAME 
HAVING (NODE_NAME, COUNT(*)) 
IN (SELECT NODE_NAME, COUNT(*) 
FROM EVENTS where STATUS = 'completed' group by node_name)) as tabletest;

alright, I've managed to figure it out, was kind of silly of me not to realize this right away.

JoshGivens
  • 128
  • 8
0

This should get you what you want

select Distinct Node_Name, COUNT(Node_Name) NodeCount
from events e
where e.Status <> 'Failed'
    AND e.Node_Name NOT IN
    (
        SELECT Node_Name
        FROM events e
        WHERE e.Status <> 'Completed'
    )
GROUP BY Node_Name

Returns:

Node_Name | NodeCount
Node_1    | 2
DiggityCS
  • 111
  • 7
0

I have tried several solution were posted. Most of them working. But I only need the simplest one because the query is for Tivoli Storage Manager (TSM) that is running on IBM DB2.

I understand that there might be some flaws for simplest method, but I don't think TSM has such capability to accommodate complicated query.

Thank you for your time. I appreciate it. Sorry for late reply. I didn't know that the reply would be this fast. This is my first post and I am new to both SQL and TSM :)

Hence, after testing the SQL query in TSM Server. This working fine:

select node_name from events group by node_name having max(status) = 'Completed'

Brian Tompsett - 汤莱恩
  • 5,753
  • 72
  • 57
  • 129
Tommy
  • 23
  • 1
  • 3