I have 3 parameters i have to score using the following formula:
rank = 6*score(name)=3*score(diagnosis)+score(description);
I need 3 scores for that right?
I know that for 1 score, you would write a query like this:
SELECT score(1), itemName
FROM item WHERE contains(description, 'database', 1) > 0
order by score(1) desc;
how would I do this for finding a keyword in a database table if I have 3 fields to search( name, description, diagnosis?)
I had this:
SELECT score(1), patient_name, score(2), diagnosis, score(3),description
FROM radiology_record r
WHERE (not sure what to put in the WHERE SECTION)
ORDER BY (6*score(1)+3*score(2)+score(3)) desc;
here is my solution based on two tables i needed. Radiology record and persons.
SELECT 6*(score(1)+score(2))+3*score(3)+score(4) as rank
FROM radiology_record r, persons p
WHERE p.person_id = r.patient_id AND contains(first_name, 'dead', 1)>0
OR contains(last_name, 'dead', 2)>0 OR contains(diagnosis,'dead', 3) > 0
OR contains(description, 'dead', 4) > 0
ORDER BY (6*(score(1)+score(2))+3*score(3)+score(4));
Related
I have written the query shown here that combines three tables and returns rows where the at_ticket_num from appeal_tickets is duplicated but against a different at_sys_ref value
select top 100
t.t_reference, at.at_system_ref, at_ticket_num, a.a_case_ref
from
tickets t, appeal_tickets at, appeals_2 a
where
t.t_reference in ('AB123','AB234') -- filtering on these values so that I can see that its working
and t.t_number = at.at_ticket_num
and at.at_system_ref = a.a_system_ref
and at.at_ticket_num IN (select at_ticket_num
from appeal_tickets
group by at_ticket_num
having count(distinct at_system_ref) > 1)
order by
t.t_reference desc
This is the output:
t_reference at_system_ref at_ticket_num a_case_ref
-------------------------------------------------------
AB123 30838974 23641583 1111979010
AB123 30838976 23641583 1111979010
AB234 30839149 23641520 1111977352
AB234 30839209 23641520 1111988003
I want to modify this so that it only returns records where t_reference is duplicated but against a different a_case_ref. So in above case only records for AB234 would be returned.
Any help would be much appreciated.
You want all ticket appeals that have more than one system reference and more than one case reference it seems. You can join the tables, count the occurrences per ticket and then only keep the tickets that match these criteria.
select *
from
(
select
t.t_reference, at.at_system_ref, at.at_ticket_num, a.a_case_ref,
count(distinct a.a_system_ref) over (partition by at.at_ticket_num) as sysrefs,
count(distinct a.a_case_ref) over (partition by at.at_ticket_num) as caserefs
from tickets t
join appeal_tickets at on at.at_ticket_num = t.t_number
join appeals_2 a on a.a_system_ref = at.at_system_ref
) counted
where sysrefs > 1 and caserefs > 1
order by t.t_reference, at.at_system_ref, at.at_ticket_num, a.a_case_ref;
Correction
It seems that SQL Server still doesn't support COUNT(DISTINCT ...) OVER (...). You can count distinct values in a subquery though. Replace
count(distinct a.a_system_ref) over (partition by at.at_ticket_num) as sysrefs,
by
(
select count(distinct a2.a_system_ref)
from appeal_tickets at2
join appeals_2 a2 on a2.a_system_ref = at2.at_system_ref
where at2.at_ticket_num = t.t_number
) as sysrefs,
An alternative workaround is to use DENSE_RANK in two directions (found here: https://stackoverflow.com/a/53518204/2270762):
dense_rank() over (partition by at.at_ticket_num order by a.a_system_ref) +
dense_rank() over (partition by at.at_ticket_num order by a.a_system_ref desc) -
1 as sysrefs,
with data as (
<your query plus one column>,
case when
min() over (partition by t.t_reference)
<>
max() over (partition by t.t_reference)
then 1 end as dup
)
select * from data where dup = 1
Imagine it like a student quiz.
10 Students get a C.
6 Students get a B.
1 Student gets an A.
Rather than showing that 1 student got an A, is there a way to show the name of the student that got that result?
This is part of the result set I get. The 2 letters represent the 2 first letters of a 6 letter string corresponding to a shelf and its warehouse. If the quantity (value on the right) is 1, I want to display the full shelf value.
I am currently using a SUBSTRING to get the 2 letters and a COUNT to get the quantity
The query I am using so far may seem complicated but here it is
SELECT DISTINCT SUBSTRING(location, 1, 2) AS ShelfNum,
COUNT(location) as Quantity
FROM warehouse_locations
WHERE unitId_unitId = 1
GROUP BY SUBSTRING(location, 1, 2)
ORDER BY ShelfNum asc
If I try to add the full location on the end if the quantity is 1, I get a group-by error
You can use a case expression to choose between max(name) and count(location) based on the result. You will need to convert the count(location) to the datatype that is returned by max(name).
Sql Server example:
select
substring(location, 1, 2) as ShelfNum
, case when count(location) = 1 then max(name)
else cast(count(location) as varchar(32))
end as Quantity
from warehouse_locations
where unitId_unitId = 1
group by substring(location, 1, 2)
order by ShelfNum asc
Also: you do not need to use distinct when you are using group by.
This would work.
SELECT CASE WHEN Quantity = 1
THEN location
ELSE ShelfNum END as ShelfNum
,Quantity
FROM (
SELECT DISTINCT SUBSTRING(location, 1, 2) AS ShelfNum,
location,
COUNT(location) as Quantity
FROM warehouse_locations
WHERE unitId_unitId = 1
GROUP BY SUBSTRING(location, 1, 2), location
)
ORDER BY ShelfNum asc
I have a table with fields StudentID, ClassID, ExamID, SubjectID and Scores
I am trying to get a sum of 7 top Scores from attempted subjects from every student. The SQL statement below is giving me the sum of scores of all the subject from the top 7 students:
SELECT TOP 7 Sum(tblScores.Scores) AS Total, tblScores.AdmissionID
FROM tblScores
WHERE (((tblScores.ExamID)=[Forms]![frmReports]![lstC]) AND ((tblScores.ClassID)=[Forms]![frmReports]![lstB]))
GROUP BY tblScores.AdmissionID
ORDER BY Sum(tblScores.Scores) DESC;
The Class and Exam criteria is read from the Form "frmReports"
Any one who can help me out?
Consider a correlated subquery to calculate a running rank of scores. Then, nest this select query in a derived table for Score aggregation, filtered by each students' top 7 scores (including ties):
SELECT main.AdmissionID, Sum(main.Scores) As [Total]
FROM
(SELECT tblScores.AdmissionID, tblScores.Scores,
(SELECT Count(*) FROM tblScores sub
WHERE sub.AdmissionID = tblScores.AdmissionID
AND sub.Scores >= tblScores.Scores) As ScoreRank
FROM tblScores
WHERE (((tblScores.ExamID)=[Forms]![frmReports]![lstC])
AND ((tblScores.ClassID)=[Forms]![frmReports]![lstB]))
) As main
WHERE main.ScoreRank <= 7
GROUP BY main.AdmissionID
Try this:
SELECT TOP 7 Sum(tblScores.Scores) AS Total, tblScores.AdmissionID
FROM tblScores
HAVING (((tblScores.ExamID)=[Forms]![frmReports]![lstC]) AND ((tblScores.ClassID)=[Forms]![frmReports]![lstB]))
GROUP BY tblScores.AdmissionID
ORDER BY Sum(tblScores.Scores) DESC;
# Parfait - Thank you for your guidance. I have actually tweaked your solution to get a perfect answer: Here is the sql:
SELECT Dupe.AdmissionID, Dupe.Scores, Dupe.ScoreRank
FROM (SELECT qryFilteredScores.AdmissionID, qryFilteredScores.Scores, (SELECT Count(*) FROM qryFilteredScores AS sub
WHERE sub.AdmissionID = qryFilteredScores.AdmissionID AND sub.Scores >qryFilteredScores.Scores)+ 1 AS ScoreRank FROM qryFilteredScores WHERE (((qryFilteredScores.ExamID)=Forms!frmReports!lstC) And ((qryFilteredScores.ClassID)=Forms!frmReports!lstB))) AS Dupe
WHERE (((Dupe.Scores)<>0) AND ((Dupe.ScoreRank)<=7));
Alternatively, you can use a derived table or stored query (where you save derived table as separate object referenced in this query) and avoid inline subqueries:
SELECT Dupe.AdmissionID, Total.TotalScore
FROM qryFilteredScores AS Dupe
INNER JOIN
(SELECT sub.AdmissionID, Sum(sub.Scores) As TotalScore
FROM qryFilteredScores sub
WHERE ([AdmissionID]=Dupe.[AdmissionID]
AND ((sub.ClassID)=[Forms]![frmReports]![lstB])
AND ((tblScores.ExamID)=[Forms]![frmReports]![lstC]))
GROUP BY sub.AdmissionID) AS Total
ON Dupe.AdmissionID = Total.AdmissionID
GROUP BY Dupe.AdmissionID, Total.TotalScore
ORDER BY Dupe.AdmissionID;
I have searched a lot, but most of solutions are for concatenation option and not what I really want.
I have a table called X (in a Postgres database):
anm_id anm_category anm_sales
1 a_dog 100
2 b_dog 50
3 c_dog 60
4 a_cat 70
5 b_cat 80
6 c_cat 40
I want to get total sales by grouping 'a_dog', 'b_dog', 'c_dog' as dogs and 'a_cat', 'b_cat', 'c_cat' as cats.
I cannot change the data in the table as it is an external data base from which I am supposed to get information only.
How to do this using an SQL query? It does not need to be specific to Postgres.
Use case statement to group the animals of same categories together
SELECT CASE
WHEN anm_category LIKE '%dog' THEN 'Dogs'
WHEN anm_category LIKE '%cat' THEN 'cats'
ELSE 'Others'
END AS Animals_category,
Sum(anm_sales) AS total_sales
FROM yourtables
GROUP BY CASE
WHEN anm_category LIKE '%dog' THEN 'Dogs'
WHEN anm_category LIKE '%cat' THEN 'cats'
ELSE 'Others'
END
Also this query should work with most of the databases.
By using PostgreSQL's split_part()
select animal||'s' animal_cat,count(*) total_sales,sum(anm_sales) sales_sum from(
select split_part(anm_cat,'_',2) animal,anm_sales from x
)t
group by animal
sqlfiddle
By creating split_str() in MySQL
select animal||'s' animal_cat,count(*) total_sales,sum(anm_sales) sales_sum from(
select split_str(anm_cat,'_',2) animal,anm_sales from x
)t
group by animal
sqlfiddle
You could group by a substr of anm_catogery:
SELECT SUBSTR(anm_catogery, 3) || 's', COUNT(*)
FROM x
GROUP BY anm_catogery
If you have a constant length of the appendix like in the example:
SELECT CASE right(anm_category, 3) AS animal_type -- 3 last char
, sum(anm_sales) AS total_sales
FROM x
GROUP BY 1;
You don't need a CASE statement at all, but if you use one, make it a "simple" CASE:
Simplify nested case when statement
Use a positional reference instead of repeating a possibly lengthy expression.
If the length varies, but there is always a single underscore like in the example:
SELECT split_part(anm_category, '_', 2) AS animal_type -- word after "_"
, sum(anm_sales) AS total_sales
FROM x
GROUP BY 1;
I have a table with a column named Skills which contains comma separated values for different employees like
EmpID Skills
1 C,C++,Oracle
2 Java,JavaScript,PHP
3 C,C++,Oracle
4 JavaScript,C++,ASP
5 C,C++,JavaScript
So I want to write a query which will order all the employees first who knows JavaScript, how can I get this result?
You should not use one attribute to store multiple values. That goes against relation DB principles.
Instead of that you should create additional table to store skills and refer to employee in it. Then, your query will looks like:
SELECT
*
FROM
employees
LEFT JOIN employees_skills
ON employee.id=employees_skills.employee_id
WHERE
employees_skills='JavaScript'
Try this
SELECT *
FROM
(
SELECT *
,CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END AS Rnk
FROM MyTable
) T
ORDER BY rnk,EmpID
DEMO
OR
SELECT * FROM #MyTable
ORDER BY CASE WHEN Skills LIKE '%JavaScript%' THEN 0 ELSE 1 END,EmpID
select EmpID, Skills
from Table1
order by case when Skills like '%JavaScript%' then 0 else 1 end
Try this:
SELECT *
FROM YourTable
ORDER BY PATINDEX('%JavaScript%', Skills) DESC
But this is a bad way. You should really normalize your table.
For MySQL
select Skills from myTable
order by case Skills
when "Javascript" then 0
when "Java" then 1 when "C++" then 2
end
and so on
For SQL Server
select Skills from myTable
order by case
when Skills="Javascript" then 1
when Skill="Java" then 2
else 3
end
Make sure to start SQL server from 1 (That I'm not sure).
Include an else before end that will show all remaining results.
For more details about SQL Server see this or see this
This works for DB2/400:
with s (id, skill, rest) as
(select id, '', sk from skills
union all
select id, substr(rest, 1, locate(',',rest)-1),
substr(rest,locate(',',rest)+1)
from s
where locate(',',rest) > 0)
select id, skill from s
where skill = 'JavaScript'
order by id