SQL Query - find the number of unique data entry - sql

I have the following table named FruitCountry and I would like to check number of unique entries per fruit, I think I can achieve that by first grouping by fruit then countryID, then select distinct data and use COUNT() function to find the size, yet is there a less tedious way to achieve that? Thanks!
Fruit CountryID
-----------------
Apple 1
Apple 2
Apple 1
Grapes 3
Grapes 3
Fruit # of unique entries
-----------------
Apple 2
Grapes 1

Just count the unique countryid.
select Fruit, count(distinct CountryId)
from FruitCountry
group by Fruit

Use count(distinct columnname) to achieve distinct count of a column within the group:
select Fruit, count(distinct CountryId) [# of unique entries]
from FruitCountry
group by Fruit

If you have large amount of data it is a good idea to use a temporary table.
IF OBJECT_ID(N'tempdb..#fruits') IS NOT NULL DROP TABLE #fruits
IF OBJECT_ID(N'tempdb..#temp') IS NOT NULL DROP TABLE #temp
CREATE TABLE #fruits(Fruit VARCHAR(10), Id INT )
--INSERT INTO #fruits
INSERT INTO #fruits ( Fruit, Id ) VALUES ('Apple', 1 )
INSERT INTO #fruits ( Fruit, Id ) VALUES ( 'Apple', 2 )
INSERT INTO #fruits ( Fruit, Id ) VALUES ('Apple', 1 )
INSERT INTO #fruits ( Fruit, Id ) VALUES ('Grapes', 3 )
INSERT INTO #fruits ( Fruit, Id ) VALUES ('Grapes', 3 )
--SELECT * FROM #fruits
--Temp Table to hold Distinct Values
CREATE TABLE #temp (Fruit VARCHAR(10) , Id INT )
INSERT INTO #temp (Fruit, id ) SELECT DISTINCT Fruit, id FROM #fruits
--Final Query to get NoOfUniqueEntries
SELECT Fruit, count (*) AS NoOfUniqueEntries FROM #temp
GROUP BY Fruit
DROP TABLE #temp, #fruits

Related

MariaDB concatenate 2 tables with same number of rows

Say I have 2 tables with exactly SAME number of rows, but no other obvious relations:
tableA
ID
items
1
banana
2
orange
tableB
itemID
volume
5550
50
5551
70
Can I join these 2 tables horizontally, to form 1 table like the following?
ID
items
itemID
volume
1
banana
5550
50
2
orange
5551
70
If you have 2 tables with exactly SAME number of rows, but no other obvious relations and on both tables , respectively ID and itemID defines the uniqueness of the rows you can apply MySQL ROW_NUMBER Function and join on the row_number, the order by clause is important.
Try:
SELECT tbla.ID, tbla.Items, tblb.ItemId, tblb.volume
FROM (
SELECT ID, Items, row_number() over( order by ID desc )row_numA
FROM TableA
)tbla
INNER join
( SELECT ItemId,volume,row_number() over(order by ItemId desc)row_numB
FROM TableB
) tblb ON tbla.row_numA=tblb.row_numB
order by tbla.ID asc;
https://dbfiddle.uk/?rdbms=mariadb_10.6&fiddle=15d13d29a84a55c4d029115c87eebe8f
try this
create table TableA(ID INT, Items varchar(20));
create table TableB(ItemId INT, volume varchar(20));
insert into TableA(Id, items) values (1, 'banana'), (2, 'orange');
insert into TableB(ItemId, volume) values (5550, '50'), (5551, '70');
SELECT A.ID, A.Items, B.ItemId, B.volume
FROM
(
SELECT ID, Items, rownum()R
FROM TableA
)A INNER join
(
SELECT ItemId,volume,rownum()R
FROM TableB
)B ON A.R=B.R

How to delete the oldest record and retain the recent records using a temp table in SQL?

How to delete the oldest record but retain the recent records in SQL in the below given example ?
The output display and records removal is expected in a temp table without affecting the main table
Current:
StockId Name CreatedDate Status
1 Apple 10/09/2017 2
1 Apple 11/09/2017 2
1 Apple 12/09/2017 2
2 Orange 15/09/2017 2
2 Orange 16/09/2017 1
Expected:
StockId Name CreatedDate Status
1 Apple 12/09/2017 2
2 Orange 16/09/2017 1
try Something like this:
WITH cte
AS
(
SELECT *,row_number() over (partition by StockId, Name order by CreatedDate desc) as row_number 
FROM yourtable
) DELETE FROM cte WHERE row_number>1
If you simply want to get the newest record per stock ID into the new table, use an insert select. Use ROWNUMBER to rank your records.
insert into temp (stockid, name, createddate, status)
select stockid, name, createddate, status
from
(
select
stockid, name, createddate, status,
rownumber() over (partition by stockid order by createddate desc) as rn
from mytable
)
where rn = 1;
You could use a nested query that shows the StockId and the most recent data. Then, remove all the row in the original table that aren't in the nested query:
/* Create few records in this table */
INSERT INTO MyTable VALUES(1, 1, 'Apple', '2017/09/10', 2);
INSERT INTO MyTable VALUES(2, 1, 'Apple', '2017/09/11', 2);
INSERT INTO MyTable VALUES(3, 1, 'Apple', '2017/09/12', 2);
INSERT INTO MyTable VALUES(4, 2, 'Orange', '2017/09/15', 2);
INSERT INTO MyTable VALUES(5, 2, 'Orange', '2017/09/16', 2);
DELETE FROM MyTable
WHERE (StockId, CreatedData) NOT IN
(
SELECT StockId, Max(CreatedData)
FROM MyTable GROUP BY StockId
);
/* result*/
StockId Name CreatedDate Status
1 Apple 2017/09/12 2
2 Orange 2017/09/16 1

How to remove common fields in two tables

I have two tables , table 1 and table 2.
The fields of table 1 are :
book,pen,pencil,bag
The fields of table 2 are :
car,van,book,bike,pencil
When I run the query I want the query to ignore the duplicate or common fields and return the other field.
The output should be as follows,
car,van,bike,pen,bag
Perhaps:
SELECT x.thing FROM
(
SELECT thing FROM dbo.Table1
UNION ALL
SELECT thing FROM dbo.Table2
) X
GROUP BY x.thing
Having Count(*) = 1
Demo
However, this will also remove items that are duplicates in their table which might or might not be desired.
Have you tried sth like this:
delete form X
where (car =
Select distinct car
from X
where x);
distinct--> return the differents values.
try this one:
declare #table1 table (col1 varchar(max))
declare #table2 table (col1 varchar(max))
insert into #table1 values
('book'),('pen'),('pencil'),('bag')
insert into #table2 values ('car'),('van'),('book'),('bike'),('pencil')
;with cte
as (
select COUNT(1) as total_item, col1 from (
select col1 from #table1
union all
select col1 from #table2
)a group by col1
)
select col1 from cte where total_item = 1
WITH uniontables AS (
SELECT NULL AS car,
NULL AS van,
book,
NULL AS bike,
pen,
pencil,
bag
FROM [Table 1 ]
UNION
SELECT car,
van,
book,
bike,
NULL AS pen,
pencil,
NULL AS bag
FROM [Table 2 ] )
SELECT DISTINCT * FROM uniontables

Select multi identity values for multiple inserts along with columns not inserted into the table

I am inserting only 1 column into TempId table i.e name from a select statement
How do i get corresponding orderId for the identity column.
INSERT INTO tempId
output inserted.ID
Select name FROM (
select 'erty' as name, 1 as orderid union
select 'rth' as name, 2 as orderid union
select 'yt' as name, 3 as orderid union
select '345' as name, 4 as orderid union
select 'rtyu' as name, 5 as orderid union
select 'uio' as name, 6 as orderid union
select 'yu' as name, 7 as orderid union
select 'xzf' as name, 8 as orderid
) as a
PS Note: SELECT with union is only done for sample query. Ideally I will get things from another table.
You put the id and any other fields you need to use later in a table varaiable or temp table by using the OUTPUT clause
DECLARE #MyTableVar table( ID int, orderid int);
INSERT mytable (field1, orderID)
OUTPUT INSERTED.ID, INSERTED.OrderID
INTO #MyTableVar
SELECT FIELD2, orderid FROM Myothertable
Now you have the data available in #MyTableVar to do inserts to child tables or the other work you wanted to do.
just arrange the columns:
create table #tempID( id int, name varchar(50))
INSERT INTO #tempID (name, id)
output inserted.ID
Select name, orderid FROM (
select 'erty' as name, 1 as orderid union
select 'rth' as name, 2 as orderid union
select 'yt' as name, 3 as orderid union
select '345' as name, 4 as orderid union
select 'rtyu' as name, 5 as orderid union
select 'uio' as name, 6 as orderid union
select 'yu' as name, 7 as orderid union
select 'xzf' as name, 8 as orderid
) as a
This is an example on inserting values directly. If there are no triggers you can get ##IDENTITY.
insert into [FTSwordDef] ([word]) values ('value')
select scope_identity();
Scope_identity (and the evil ##) will only return the last iden. If you are inserting multiple rows then I think you would need to loop in a SP and build up the list of iden. Iden is created by the insert and is not available IN the insert to my knowledge.
If you held a tablock on the the insert and retrieved the last identity and how many rows were inserted then in theory the insert got the last x inden values. If your insert was sorted you would know what iden went with which row.

Group By and Aggregate function

I want to write an efficient query which returns a list of fruits by type, the lowest price for the type of fruit and the name of the fruit. Right now, I have a query which return me the fruit type and the lowest price for that type (see below). But I am unable to get the name of the cheapest fruit.
Any idea how I can achieve that? Thanks.
CREATE TABLE Fruits (
[type] nvarchar(250),
[variety] nvarchar(250),
[price] money
)
GO
INSERT INTO Fruits VALUES ('Apple', 'Gala', 2.79)
INSERT INTO Fruits VALUES ('Apple', 'Fuji', 0.24)
INSERT INTO Fruits VALUES ('Apple', 'Limbertwig', 2.87)
INSERT INTO Fruits VALUES ('Orange', 'Valencia', 3.59)
INSERT INTO Fruits VALUES ('Pear', 'Bradford', 6.05)
SELECT type, MIN(price)
FROM Fruits
GROUP BY [type]
Use:
SELECT f.*
FROM FRUITS f
JOIN (SELECT t.type,
MIN(t.price) AS min_price
FROM FRUITS t
GROUP BY t.type) x ON x.type = f.type
AND x.min_price = f.price
I gather you're using SQL Server - if v2005 or newer, you could also use analytic/rank/windowing functions instead:
SELECT f.type, f.variety, f.price
FROM (SELECT t.type, t.variety, t.price,
ROW_NUMBER() OVER (PARTITION BY t.type ORDER BY t.price) AS rank
FROM FRUITS t) f
WHERE f.rank = 1
There are a number of ways to do this, one solution is below.
SELECT F2.type, f2.variety, f2.price
FROM
(
SELECT type, min(price) as price
FROM Fruits
GROUP BY [type]
) as MinData
INNER JOIN Fruits F2
ON (MinData.type = Type = F2.Type
AND MinData.price = F2.Price)
Keep in mind that if you have multiple items in a category with the same price at the minimum you will get multiple results.
There's a simple trick you can use for this sort of query if your table has a surrogate primary key. (Actually, you can do it without one, but it's more convoluted.)
The setup:
if object_id('tempdb..#Fruits') is not null drop table #Fruits
create table #Fruits (
[id] int identity(1,1) not null,
[type] nvarchar(250),
[variety] nvarchar(250),
[price] money
)
insert into #Fruits ([type], [variety], [price])
select 'Apple', 'Gala', 2.79 union all
select 'Apple', 'Fuji', 0.24 union all
select 'Apple', 'Limbertwig', 2.87 union all
select 'Orange', 'Valencia', 3.59 union all
select 'Pear', 'Bradford', 6.05
And now the SQL:
select * -- no stars in PROD!
from #Fruits a
where
a.id in (
select top 1 x.id
from #Fruits x
where x.[type] = a.[type]
order by x.price
)