count distinct value of field on every row - sql

table: item_tbl
|item_id |serial_code|item_name|
------------------------------
| 1 | x35 | bullet |
| 2 | 6ox | cord |
| 3 | 0hg | cord |
| 4 | a73 | tv |
| 5 | lo5 | bullet |
I tried to use SELECT serial_code, item_name, COUNT(item_name) FROM item_tbl but not what i expected of course. How can I count the distinct values of item_name to have something like:
|serial_code|item_name| count |
-----------------------------
| x35 | bullet | 2 |
| 6ox | cord | 2 |
| 0hg | cord | 2 |
| a73 | tv | 1 |
| lo5 | bullet | 2 |

SELECT Serial_Code, count.Item_Name, Count
FROM
item_tbl i
INNER JOIN
(
SELECT Item_Name, COUNT(1) Count
FROM item_tbl
GROUP BY item_Name
) count ON i.item_Name = count.Item_Name
Lets see if that works.

Related

SQL Server to display a view to show products at parent and child level

I have a table like this:
+----+----------+----------+-----------+
| ID | Name | Is_Group | Parent_id |
+----+----------+----------+-----------+
| 1 | Clothes | 1 | Null |
| 2 | Food | 1 | Null |
| 3 | fastfood | 1 | 2 |
| 4 | T-shirt | 0 | 1 |
| 5 | skirt | 0 | 1 |
| 6 | pizza | 0 | 3 |
| 7 | snack | 0 | 3 |
+----+----------+----------+-----------+
I would like to have a horizontal representation to use for reporting such as:
+----+---------+---------+----------+
| ID | Name | level1 | level2 |
+----+---------+---------+----------+
| 4 | T-shirt | Clothes | Null |
| 5 | skirt | Clothes | Null |
| 6 | pizza | Food | fastfood |
| 7 | snack | Food | fastfood |
+----+---------+---------+----------+
Would anyone know how to do this?
You can use two levels of left join:
select t.*,
coalesce(tpp.name, tp.name) as level1,
(case when tpp.name is not null then tp.name end) as level2
from t left join
t tp
on t.parent_id = tp.id left join
t tpp
on tp.parent_id = tpp.parent_id
where not exists (select 1
from t tc
where tc.parent_id = t.id);

SQL Query - Add column data from another table adding nulls

I have 2 tables, tableStock and tableParts:
tableStock
+----+----------+-------------+
| ID | Num_Part | Description |
+----+----------+-------------+
| 1 | sr37 | plate |
+----+----------+-------------+
| 2 | sr56 | punch |
+----+----------+-------------+
| 3 | sl30 | crimper |
+----+----------+-------------+
| 4 | mp11 | holder |
+----+----------+-------------+
tableParts
+----+----------+-------+
| ID | Location | Stock |
+----+----------+-------+
| 1 | A | 2 |
+----+----------+-------+
| 3 | B | 5 |
+----+----------+-------+
| 5 | C | 2 |
+----+----------+-------+
| 7 | A | 1 |
+----+----------+-------+
And I just want to do this:
+----+----------+-------------+----------+-------+
| ID | Num_Part | Description | Location | Stock |
+----+----------+-------------+----------+-------+
| 1 | sr37 | plate | A | 2 |
+----+----------+-------------+----------+-------+
| 2 | sr56 | punch | NULL | NULL |
+----+----------+-------------+----------+-------+
| 3 | sl30 | crimper | B | 5 |
+----+----------+-------------+----------+-------+
| 4 | mp11 | holder | NULL | NULL |
+----+----------+-------------+----------+-------+
List ALL the rows of the first table and if the second table has the info, in this case 'location' and 'stock', add to the column, if not, just null.
I have been using inner and left join but some rows of the first table disappear because the lack of data in the second one:
select tableStock.ID, tableStock.Num_Part, tableStock.Description, tableParts.Location, tableParts.Stock from tableStock inner join tableParts on tableStock.ID = tableParts.ID;
What can I do?
You can use left join. Here is the demo.
select
s.ID,
Num_Part,
Description,
Location,
Stock
from Stock s
left join Parts p
on s.ID = p.ID
order by
s.ID
output:
| id | num_part | description | location | stock |
| --- | -------- | ----------- | -------- | ----- |
| 1 | sr37 | plate | A | 2 |
| 2 | sr56 | punch | NULL | NULL |
| 3 | sl30 | crimper | B | 5 |
| 4 | mp11 | holder | NULL | NULL |

getting an average of a count of a group sql impala

Given a table like;
+----+----------+
| id | modality |
+----+----------+
| 1 | CT |
| 1 | SC |
| 1 | MR |
| 1 | CT |
| 2 | SC |
| 3 | CT |
| 3 | CT |
| 3 | MR |
| 4 | MR |
| 4 | CT |
+----+----------+
Something like;
SELECT AVG(modality_count)
FROM (
SELECT id, COUNT(modality) AS modality_count
FROM TABLE
GROUP BY id
) a
Would get the average amount of modality per patient, and output something like:
+---------------------+
| AVG(modality_count) |
+---------------------+
| 1.4 |
+---------------------+
the following query:
SELECT CONCAT(CAST(COUNT(*) AS string), ' ' , modality) AS count_m
FROM TABLE
GROUP BY modality
would get the count of the number of rows for each modality, like:
+---+---------+
| | count_m |
+---+---------+
| 1 | 560 CT |
| 2 | 2 SC |
| 3 | 473 MR |
+---+---------+
Let's say there are 1035 rows, 726 unique ids, and each id is likely to have 1.4 scans (either CT, SC, MR). How would you get the average number of CT/ MT/ SC?
desired output something like:
+----------+---------+
| modality | AVG(id) |
+----------+---------+
| CT | 0.77 |
| SC | 0.003 |
| MR | 0.65 |
+----------+---------+
Thanks in advance

How to get non-existing rows in many to many relationship

I am having following three tables
products
------------------
| id | name |
------------------
| 1 | Ariel |
| 2 | Milk |
------------------
price_list
-----------------------
| id | name |
-----------------------
| 1 | Trade Price |
| 2 | Net Price |
| 3 | Retail Price |
-----------------------
product_prices (it has only two records for product 'Ariel')
----------------------------------------------
| id | product_id | price_list_id | price |
----------------------------------------------
| 1 | 1 | 1 | 100 |
| 2 | 1 | 2 | 110 |
----------------------------------------------
Desired Result:
------------------------------------------------------------
| id | product_name | prices |
------------------------------------------------------------
| | | | id | price_list_name | price | |
| 1 | Ariel | -------------------------------- |
| | | | 1 | Trade Price | 100 | |
| | | | 2 | Net Price | 110 | |
| | | | 3 | Retail Price | null | |
| | | -------------------------------- |
| | | | id | price_list_name | price | |
| 2 | Milk | -------------------------------- |
| | | | 1 | Trade Price | null | |
| | | | 2 | Net Price | null | |
| | | | 3 | Retail Price | null | |
-------------------------------- |
------------------------------------------------------------
I tried following query to get a cross between products and price_list
SELECT p.id,
p.NAME,
pl.id,
pl.NAME
FROM products p
CROSS JOIN price_list pl
WHERE pl.id NOT IN (SELECT product_id
FROM product_prices)
Any idea how to achieve the desired result?
I think something like this. I changed the names of the fields and tables for short. I also display all the fields.
select * from t1 cross join t2 left join t3 on t1.id = t3.t1_id and t2.id = t3.t2_id order by t1.id, t2.id;
+----+-------+----+--------------+------+-------+-------+-------+
| id | name | id | name | id | t1_id | t2_id | price |
+----+-------+----+--------------+------+-------+-------+-------+
| 1 | Ariel | 1 | Trade Price | 1 | 1 | 1 | 100 |
| 1 | Ariel | 2 | Net Price | 2 | 1 | 2 | 110 |
| 1 | Ariel | 3 | Retail Price | NULL | NULL | NULL | NULL |
| 2 | Milk | 1 | Trade Price | NULL | NULL | NULL | NULL |
| 2 | Milk | 2 | Net Price | NULL | NULL | NULL | NULL |
| 2 | Milk | 3 | Retail Price | NULL | NULL | NULL | NULL |
+----+-------+----+--------------+------+-------+-------+-------+
products -> t1
price_list -> t2
product_prices -> t3

Having Groups based on distinct count of another column

I have a table as follow :
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Sales | ABC |
| 1 | Design | XYZ |
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
| 3 | Sales | XYZ |
+-------------+-----------+------+
I want to output only the groups that have unique teams greater than 3.
Only group 2 has this condition so the output is :
Expected Output:
+-------------+-----------+------+
| GroupNumber | TeamName | Goal |
+-------------+-----------+------+
| 2 | Design | XYZ |
| 2 | Sales | XYZ |
| 2 | technical | XYZ |
| 2 | Support | XYZ |
+-------------+-----------+------+
not sure how to utilize this in subquery
SELECT count(Distinct(TeamName))
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
Simply put it in a Subquery:
select *
from mytable
where [GroupNumber] in
(
SELECT [GroupNumber]
FROM mytable
group by [GroupNumber]
HAVING COUNT(Distinct[TeamName])>3
)
Please try
SELECT *
FROM mytable where GroupNumber in (select GroupNumber
FROM mytable group by TeamName
HAVING COUNT(TeamName)>3)