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
Related
So I've got a small DB that has like subsections that come under a single section. Unfortunately, the DB doesn't have a "section" column and just the subsections and they have a "Inventory" column that has either "Computer" or "Laptop" in it. I've made a query that at the very least provides me with the total count of each of these "Inventory" column against each subsection.
However, I'm trying to combine the subsections into a single row and the total count of those subsections alongside it as well. Example of what I'm trying to say:
subsections
inventory
a_subsec1
comp
a_subsec1
comp
a_subsec2
lap
a_subsec2
comp
a_subsec3
lap
a_subsec3
comp
What I'm currently getting:
d_sub
inv_count_comp
a_subsec1
2
a_subsec2
1
a_subsec3
1
What I WANT to get:
D_SUB
total_comp_count
a_sec
4
Here's the query that I'm currently running to get that second table:
SELECT DISTINCT "subsections", COUNT("inventory") FROM mytable WHERE "inventory" = 'comp' GROUP BY "subsections" ORDER BY "subsections" ASC
Thank you.
substring the column then you can treat all the row as same subsection.
with tb as(
select 'a_subsec1' sec,'comp' inv
union all
select 'a_subsec1' sec,'comp' inv
union all
select 'a_subsec2' sec,'lap' inv
union all
select 'a_subsec2' sec,'comp' inv
union all
select 'a_subsec3' sec,'lap' inv
union all
select 'a_subsec3' sec,'comp' inv
)
select msec,sum(inv_comp) total from(
select concat(substr(sec,1,1),'_sec') as msec,
case when inv='comp' then 1 else 0 end as inv_comp,
tb.*
from tb) z
group by msec
this query might not be the one you want without some modify but main idea is same.
db<>fiddle
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));
I have a data set which contains people, dates, food, and quantity of food. I want a query where I specify a person and a date and have two values returned: the quantity of food eaten on the date chosen and the average quantity of food eaten over the previous 7 days.
So if I pick Abe on 1/10/2013 I get "1" and "3.6" because he ate 1 piece of fruit on 1/10 and an average of 3.6 pieces of fruit each day between 1/3 and 1/9.
name,thedate,qty,food
name,thedate,qty,food
abe,1/2/2013,1,orange
abe,1/2/2013,3,pear
abe,1/3/2013,3,orange
abe,1/4/2013,2,orange
abe,1/4/2013,2,plum
abe,1/5/2013,1,orange
abe,1/7/2013,7,onion
abe,1/8/2013,2,orange
abe,1/9/2013,3,orange
abe,1/9/2013,2,pear
abe,1/10/2013,1,orange
jen,1/1/2013,2,orange
jen,1/4/2013,3,orange
jen,1/5/2013,2,orange
You need a correlated subquery to find this
Select
Parent.name
, Parent.thedate
, Parent.qty,
(SELECT avg(qty)
FROM yourTable
where name = parent.name
and thedate < parent.theDate
and theDate>=dateadd("d", datediff("d",0, parent.theDate)-7,0)
group by name) as previousSeven
from yourTable Parent
If this is actually on a per fruit-type basis you can join on that too with and fruit = parent.fruit you need to add fruit to the group by, too
Update
To find, not an average, but the sum of the number of fruit divided by the number of distinct days with data in the last 7 days you will need something more like this (it get's a lot more complicated because access doesn't support the Select count(distinct something) syntax)
Select
Name
, theDate
, qty
, sumOfPreviousSeven/distinctDaysWithDataLastSeven
from (
Select
Parent.name
, Parent.thedate
, Parent.qty
, (SELECT sum(qty)
FROM table4
where name = parent.name
and thedate < parent.theDate
and theDate>=dateadd("d", datediff("d",0, parent.theDate)-7,0)
group by name) as sumOfPreviousSeven
, (select top 1 count(distinctDates) from
(select dateadd("d", datediff("d",0, theDate),0) as distinctDates, name from table4
group by dateadd("d", datediff("d",0, theDate),0), name)
where name = parent.name
and distinctDates < parent.theDate
and distinctDates>=dateadd("d", datediff("d",0, parent.theDate)-7,0)
group by name) as distinctDaysWithDataLastSeven
from table4 Parent) as base
I have a table where many pieces of data match to one in another column, similar to a tree, and then data at the 'leaf' about each specific leaf
eg
Food Group Name Caloric Value
Vegetables Broccoli 100
Vegetables Carrots 80
Fruits Apples 120
Fruits Bananas 120
Fruits Oranges 90
I would like to design a query that will return only the distinct values of each column, and then nulls to cover the overflow
eg
Food group Name Caloric Value
Vegetables Broccoli 100
Fruit Carrots 80
Apples 120
Bananas 90
Oranges
I'm not sure if this is possible, right now I've been trying to do it with cases, however I was hoping there would be a simpler way
Seems like you are simply trying to have all the distinct values at hand. Why? For displaying purposes? It's the application's job, not the server's. You could simply have three queries like this:
SELECT DISTINCT [Food Group] FROM atable;
SELECT DISTINCT Name FROM atable;
SELECT DISTINCT [Caloric Value] FROM atable;
and display their results accordingly.
But if you insist on having them all in one table, you might try this:
WITH atable ([Food Group], Name, [Caloric Value]) AS (
SELECT 'Vegetables', 'Broccoli', 100 UNION ALL
SELECT 'Vegetables', 'Carrots', 80 UNION ALL
SELECT 'Fruits', 'Apples', 120 UNION ALL
SELECT 'Fruits', 'Bananas', 120 UNION ALL
SELECT 'Fruits', 'Oranges', 90
),
atable_numbered AS (
SELECT
[Food Group], Name, [Caloric Value],
fg_rank = DENSE_RANK() OVER (ORDER BY [Food Group]),
n_rank = DENSE_RANK() OVER (ORDER BY Name),
cv_rank = DENSE_RANK() OVER (ORDER BY [Caloric Value])
FROM atable
)
SELECT
fg.[Food Group],
n.Name,
cv.[Caloric Value]
FROM (
SELECT fg_rank FROM atable_numbered UNION
SELECT n_rank FROM atable_numbered UNION
SELECT cv_rank FROM atable_numbered
) r (rank)
LEFT JOIN (
SELECT DISTINCT [Food Group], fg_rank
FROM atable_numbered) fg ON r.rank = fg.fg_rank
LEFT JOIN (
SELECT DISTINCT Name, n_rank
FROM atable_numbered) n ON r.rank = n.n_rank
LEFT JOIN (
SELECT DISTINCT [Caloric Value], cv_rank
FROM atable_numbered) cv ON r.rank = cv.cv_rank
ORDER BY r.rank
I guess what I would want to know is why you need this in one result set? What does the code look like that would consume this result? The attributes on each row have nothing to do with each other. If you want to, say, build the contents of a set of drop-down boxes, you're better off doing these one at a time. In your requested result set, you'd need to iterate through the dataset three times to do anything useful, and you would need to either check for NULL each time or needlessly iterate all the way to the end of the dataset.
If this is in a stored procedure, couldn't you run three separate SELECT DISTINCT and return the values as three results. Then you can consume them one at a time, which is what you would be doing anyway I would guess.
If there REALLY IS a connection between the values, you could add each of the results to an array or list, then access all three lists in parallel using the index.
Something like this maybe?
select *
from (
select case
when row_number() over (partition by fruit_group) = 1 then fruit_group
else null
end as fruit_group,
case
when row_number() over (partition by name) = 1 then name
else null
end as name,
case
when row_number() over (partition by caloric) = 1 then caloric
else null
end as caloric
from your_table
) t
where fruit_group is not null
or name is not null
or caloric is not null
But I fail to see any sense in this
I have a table with parts in it:
parts (partID, sku, ....)
The SKU looks like:
ABC1232
ABC1332
DSE234
XYZ322
XYZ332
etc...
I need to group by manufacturer, so I have to get a substring of the SKU, taking the first 3 characters and then grouping them together and getting a count of them.
So the resulting output needs to look like:
MFG COUNT
ABC 2343
DSE 43
XYX 323
SELECT SUBSTRING(sku, 1, 3) AS MFG, count(*) AS COUNT
FROM parts
GROUP BY SUBSTRING(sku, 1, 3)
You can also try
SELECT LEFT(sku, 3) AS MFG, count(*) AS COUNT
FROM parts
GROUP BY LEFT(sku, 3)
Found at LEFT (Transact-SQL)