how to get first female of each tool, oracle database [duplicate] - sql

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
Oracle SQL - How to Retrieve highest 5 values of a column
I'm writing oracle query but stuck in the following problem
table is like this:
**Tool** **Name** **Gender**
Facebook Alice F
Facebook Alex M
Facebook Loong M
Facebook Jimmy M
Twitter James M
Twitter Jessica F
Twitter Sam M
Twitter Kathrine F
Google Rosa F
Google Lily F
Google Bob M
What I wanna get is the first female in each tool
the result should be like:
Facebook Alice
Twitter Jessica
Google Rosa
I'm trying to get this by using query not functions or procedures
Thank for helping

select *
from (
select row_number() over (partition by tool order by name) as rn
, Name
, Tool
from YourTable
where Gender = 'F'
) SubQueryAlias
where rn = 1 -- Only first per tool
Example at SQL Fiddle.

This is another alternative.
select min(name), tool
from yourTable
where gender = 'F'
group by tool
I'd like to have a little bit of a discussion on which is better or which does what, for me its the first time I see row_number(). Note thas this one returns the female in the alphabetical order, yours does the same by sorting in a window, what is the difference?

Related

SQL subquery as part of LIKE search

From this Question we learned to use a subquery to find information once-removed.
Subquery we learned :
SELECT * FROM papers WHERE writer_id IN ( SELECT id FROM writers WHERE boss_id = 4 );
Now, I need to search a table, both in column values that table, and in column values related by id on another table.
Here are the same tables, but col values contain more text for our "searching" reference...
writers :
id
name
boss_id
1
John Jonno
2
2
Bill Bosworth
2
3
Andy Seaside
4
4
Hank Little
4
5
Alex Crisp
4
The writers have papers they write...
papers :
id
title
writer_id
1
Boston
1
2
Chicago
4
3
Cisco
3
4
Seattle
2
5
North
5
I can use this to search only the names on writers...
Search only writers.name : (Not what I want to do)
SELECT * FROM writers WHERE LOWER(name) LIKE LOWER('%is%');
Output for above search : (Not what I want to do)
id
name
boss_id
5
Alex Crisp
4
I want to return cols from writers (not papers), but searching text both in writers.name and the writers.id-associated papers.title.
For example, if I searched "is", I would get both:
Alex Crisp (for 'is' in the name 'Crisp')
Andy Seaside (because Andy wrote a paper with 'is' in the title 'Cisco')
Output for "is" search :
id
title
writer_id
2
Chicago
4
4
Seattle
2
Here's what I have that doesn't work:
SELECT * FROM papers WHERE LOWER(title) LIKE LOWER('%is%') OR writer_id ( writers=writer_id WHERE LOWER(name) LIKE LOWER('%$is%') );
The best way to express this criteria is by using a correlated query with exists:
select *
from writers w
where Lower(w.name) like '%is%'
or exists (
select * from papers p
where p.writer_id = w.id and Lower(p.title) like '%is%'
);
Note you don't need to use lower on the string you are providing, and you should only use lower if your collation truly is case-sensitive as using the function makes the search predicate unsargable.
Since you want to return cols from writers (not papers) you should select them first, and use stuff from papers in the criteria
select *
from writers w
where
w.name like '%is%'
or
w.id in (select p.writer_id
paper p
where p.title like '%is%'
)
You can add your LOWER functions (my sql environment is not case-sensitive, so I didn't need them)

How to filter logic in SQL where element is not present for one of the user

I have table, and I need to find out the person name who dont have Iphone?
Ex. query should give from the below table as Mike.
I am trying to built logic using group by on name and Items where Item not equal to Iphone or by using 2 table but unable to get the result, can anyone suggest ?
Name
Items
Simon
Iphone
Simon
Tablate
Simon
Watch
Simon
Laptop
Jim
Iphone
Jim
Tablate
Jim
Watch
Jim
Laptop
Mike
Tablate
Mike
Watch
Mike
Laptop
I have table, and I need to find out the person name who dont have Iphone?
Using your table, you can use aggregation:
select name
from t
group by name
having sum(case when item = 'Iphone' then 1 else 0 end) = 0;
The having clause counts the number of rows with iphones. The = 0 says there are none for the name.
I like gordons answer but this might be easier to understand:
select name
from table
where name not in
(select name
from table
where item like 'Iphone')
If you need only a single record for each name go for this at the end:
group by name

Get value of one column based on another column in same table

Here is what I am trying to do: Get all people with the same boss and email the boss. I can only use the table below and I would like to add another column showing the boss email which is found in the table.
id name email boss
-------------------------------------------
1 Apple Apple#alo.com Rita
2 Bob Bob#alo.com Rita
3 Charlie Charlie#alo.com Nuna
4 Dan Dan#alo.com Rita
5 Rita Rita#alo.com Sheeba
6 Nuna Nuna#alo.com Sheeba
Thanks for any help.
You use a join to do that. It looks like the code below. When joining to the same table you have to use an alias.
SELECT base.name, boss.email as boss_email
from the_table_name_you_did_not_say as base
join the_table_name_you_did_not_say as boss on base.boss = boss.name
Technically you don't have to use an alias on the base table if you select a wildcard * for some platforms

SQL Tinder to prioritize order for users who already like you

profile
---
id name
1 John
2 Jane
3 Jill
...
swipe
---
id profile_1_id profile_2_id liked
1 2 1 true
2 3 1 false
...
If you've used Tinder before, you might recognize that it seems to fetch an initial card deck that consists of:
users who already like you that you can instantly match with, pushed to the top
other users
(out of scope for this question but it also sprinkles in some more attractive users)
If we extend the example to 100+ users, id=1 John was looking at the app, and we fetched with a limit of 20, it would guarantee Jane comes back (since Jane already likes John and John could match right away) + 19 others to fill the rest of John's deck to keep John swiping for more.
What is the SQL for "get people who like John first then fill the rest with random users"? Would this be a WHERE(case if else) or some other statement?
Here is a query that should meet your need.
It works by using a conditional sorting with CASE. Users that liked John will are given higher priority, and will appear sorted by id. Other users are given a lower, random, priority ; this also means, for a given user, this part of list will not always be the same (which, I believe, fits your purpose). The number of output records is then controlled by a LIMIT clause.
I tested the query in this db fiddle. You need to replace the question mark (?) in the CASE clause with the id of user for which you are generating a card (1 for John in your sample data).
SELECT
p.id,
p.name
FROM
profile p
LEFT JOIN swipe s on s.profile_1_id = p.id
ORDER BY
CASE s.profile_2_id
WHEN ? THEN 0
ELSE FLOOR(random() * 10) + 1
END,
p.id
LIMIT 20
You could try something like this but I think you're oversimplifying. Do you want to exclude not liked people from the others?
select * from profile p
left outer join swipe s on (p.id=profile_1_id and s.profile_2_id = 1 and liked = true)
where
p.id<>1
order by coalesce(profile_2_id , random()*-1000000) desc
limit 20

Exclude entire row based on based on values from another query

I am using MS Access and I have a rather complex situation.
I have Respondents who are linked to varying numbers of different Companies via 2 connecting tables. I want to be able to create a list of distinct customers which excludes any customer associated with Company X.
Here is a pic of the relationships that are involved with the query.
And here is an example of what I'm trying to achieve.
RespondentRef | Respondent Name
8 Joe Bloggs
.
RespondentRef | GroupRef
8 2
.
GroupRef | CompanyRef
2 10
.
CompanyRef | CompanyName
10 Ball of String
I want a query where I enter in 'Ball of String' for the company name, and then it produces a list of all the Respondents (taken from Tbl_Respondent) which completely excludes Respondent 8 (as he is linked to CompanyName: Ball of String).
Tbl_Respondent
RespondentRef | Respondent Name
... ...
7 Bob Carlyle
9 Anton Boyle
I have tried many combinations of subqueries with <> and NOT EXISTS and NOT IN and nothing seems to work. I suspect the way these tables are linked may have something to do with it.
Any help you could offer would be very much appreciated. If you have any questions let me know. (I have made best efforts, but please accept my apologies for any formatting conventions or etiquette faux-pas I may have committed.)
Thank you very much.
EDIT:
My formatted version of Frazz's code is still turning resulting in a syntax error. Any help would be appreciated.
SELECT *
FROM Tbl_Respondent
WHERE RespondentRef NOT IN (
SELECT tbl_Group_Details_Respondents.RespondentRef
FROM tbl_Group_Details_Respondents
JOIN tbl_Group_Details ON tbl_Group_Details.GroupReference = tbl_Group_Details_Respondents.GroupReference
JOIN tbl_Company_Details ON tbl_Company_Details.CompanyReference = tbl_Group_Details.CompanyReference
WHERE tbl_Company_Details.CompanyName = "Ball of String"
)
This should do what you need:
SELECT *
FROM Tbl_Respondent
WHERE RespondentRef NOT IN (
SELECT gdr.RespondentRef
FROM Tbl_Group_Details_Respondent gdr
JOIN Tbl_Group_Details gd ON gd.GroupRef=gdr.GroupRef
JOIN Tbl_Company_Details cd ON cd.CompanyRef=gd.CompanyRef
WHERE cd.CompanyName='Ball of String'
)