Find rows that have both boolean in a column - sql

I have oracle11 table like this:
id name have_child
----------- ---------- ------------
1 Alison N
2 Mary N
3 Meg Y
4 Mary N
5 Meg N
where have_child is probably Boolean = Y/N.
I want to do query to list wrong behavior where one name can be Y and N - like Meg:
id name have_child
----------- ---------- ------------
3 Meg Y
5 Meg N
As a result I want to list entire rows.
I do not want to list proper duplicates - like Mary:
id name have_child
----------- ---------- ------------
2 Mary N
4 Mary N
I know how to count particular names and list what names appears more than 1 time like this:
SELECT name from table
GROUP BY name
HAVING COUNT(*)>1;

This could be a way:
select id, name, have_child
from (
select t.*,
count(distinct have_child) over (partition by name) as num
from yourTable t
)
where num > 1
The inner query simply lists all the records of the table, adding a column which gives the number of different values of have_child for the same name.
The external one simply filters for rows in which this number is greater than 1.

Related

I need a query to solve the case I mentioned below

STUDENT table which is used to store the student info and COURSE table which is used to store the Course info. the relationship between STUDENT and COURSE is one to many.
"Not Equal" and "Not Contains" are not giving the correct results incase of one to many relationship.(if we make the direct left join with COURSE table)
sample query
SQL Fiddle
Table: STUDENT
id name
----------- ----------
1 a
2 b
3 c
Table: COURSE
id name student
----------- ---------- ----------
10 x 1
11 y 1
11 y 2
10 x 3
In the example, I would like to obtain all students who are not associated with the course 'y'. But, when I add join and then apply filter, if a student (here student 'a') is associated with 'y' and another subject, he is shown in result. But, I
should not have student 'a' in the result as he is associated with 'y'.
In the following query, I was only expecting a single result
SELECT * FROM stu
JOIN cour ON stu.id = cour.student
WHERE cour.name != 'y'
id name id name student
----------- ---------- ----------- ---------- ----------
1 a 10 x 1
3 c 10 x 3
And multiple logical operations are also possible in the criteria. could you please suggest a query to achieve this?

Generate frequency table from sql using Count with user defined condition

Basically I need to generate a frequency table using sql, and I have a sample table like this:
user_id user_label code1 date
------ ----------- ----- ------
1 x a 01-01
1 x a 01-01
1 x a 01-02
1 x b 01-01
1 x c 01-02
1 y a 01-01
2 x a 01-01
etc
The rule to count occurrences is if two rows have the same user_id ,user_label and date ,then repeated codes should only be counted once.
For example, for the first two rows the frequency table should be :
user_id user_label code1 count_code_1
-------- ----------- ----- ------------
1 x a 1
Because even though there are two instances of a, but they happen on the same date so should only be counted once and I need do this for every unique codes in code_1 column
for all combinations of user_id + user_label
After processing the third row , the frequency table should be :
user_id user_label code_1 count_code_1
-------- ----------- ------ ------------
1 x a 2
Since although is the same code ('a') but it happens on a different date (01-02)
In the end, for the sample table given above, the desired result should be
user_id user_label code_1 count_code_1
-------- ----------- ------ -------------
1 x a 2
1 x b 1
1 x c 1
1 y a 1
2 x a 1
What I have so far is
select t.user_id, t.user_label, t.code_1, count(###)
from t
group by t.code_1,t.user_id, t.user_label
The problem is
1. I don't know what to put inside the count 2. I don't know how to incorporate the condition on date in to this query.
Any suggestion, correction would be greatly appreciated.
You seem to want count(distinct date):
select t.user_id, t.user_label, t.code_1,
count(distinct date)
from t
group by t.code_1,t.user_id, t.user_label

Unpivot columns into rows (oracle)

much like this original SO Pivoting rows into columns dynamically in Oracle
but i would like to do the opposite
how can i get
ID NAME AGE GENDER STATUS
---- ----- ----- ------ --------
1 Bob 30 male
2 Susan married
into this
ID K V
---- ----- -----
1 name Bob
1 age 30
1 gender male
2 name Susan
2 status married
You are looking for unpivot.
select * from t
unpivot (
v for k in ("NAME","AGE","GENDER","STATUS")
) u
You may have a type mismatch if the age column is an integer. In that case convert it to a character before unpivoting.
select *
from (select id,name,to_char(age) age,gender,status from t) t
unpivot (
v for k in ("NAME","AGE","GENDER","STATUS")
) u

Using with CUBE on the same column twice to output perculated results

Hypothetically, I have a table that consists of int values only one column with values like 1,2,3 etc., called Number.
When I try:
SELECT Number,Number FROM Table Group By Number WITH CUBE
It returns:
Number Number
------ ------
1 1
2 2
3 3
I was expecting it to return something more like this:
Number Number
------ ------
1 1
1 2
1 3
2 1
2 2
2 3
and so forth... (with every combination)
How would this be possible, WITH CUBE doesn't seem to be cutting it here.
It seems you want the cartesian product:
SELECT a.Number, b.Number
FROM [Table] a, [Table] b
Or, another way to write:
SELECT a.Number, b.Number
FROM [Table] a CROSS JOIN [Table] b

Comparing two columns from different tables of different types in SQL

There is a column that exists in 2 tables. In table 1, this column contains values in binary form (int), 1 and 0, while the other table contains the column in form 'Y' and 'N'.
Essentially I need to display rows in table 1 that contain values that are different from values in table 2 for that column. How do I compute 1 to Y and 0 to N for comparison?
Example:
Table 1:
DateRecorded SchoolName StudentName isAbsent hasPassed
------------ ---------- ----------- -------- ---------
2011-04-03 ABC John Y Y
2011-04-05 ABC John N Y
Table 2:
DateRecorded SchoolName StudentName isAbsent hasPassed
------------ ---------- ----------- -------- ---------
2011-04-03 ABC John 0 1
2011-04-05 ABC John 0 1
Should return row:
2011-04-03 ABC John Y Y
from Table 1 as this row is conflicting with the same row in Table 2.
Try this:
SELECT * FROM tbl1
EXCEPT
SELECT
daterecorded,
schoolname,
studentname,
CASE isAbsent WHEN 1 THEN 'Y' WHEN 0 THEN 'N' END AS isAbsent,
CASE hasPassed WHEN 1 THEN 'Y' WHEN 0 THEN 'N' END AS hasPassed
FROM tbl2
SQL-Fiddle Demo