SQLite - Assign a sequential number to each range of rows - sql

In my table every color has index, which defines color order inside country, in every country order may be different.
country
color
color_order
other_data
Canada
green
1
Canada
green
1
Canada
green
1
Canada
red
2
Canada
red
2
Canada
yellow
3
Canada
yellow
3
France
red
1
France
blue
2
France
blue
2
After removing one of colors (all 'red' rows), I need to re-number color_order for each country.
Expected result:
country
color
color_order
other_data
Canada
green
1
Canada
green
1
Canada
green
1
Canada
yellow
2
Canada
yellow
2
France
blue
1
France
blue
1
It should be something like nested loop to iterate through country/color, seems query should include:
ROW_NUMBER() OVER (PARTITION BY country ORDER BY color_order)
Any ideas please?

uses a Common Table Expression (CTE) to first select the rows that you want to keep in the table (all rows where the color is not 'red'). The ROW_NUMBER() function is then used to assign a new color_order to each row based on the order of the color_order column within each country (partition). Finally, an UPDATE statement is used to update the color_order values in the original table to the new values computed in the CTE.
WITH cte AS (
SELECT country, color, color_order, other_data,
ROW_NUMBER() OVER (PARTITION BY country ORDER BY color_order) AS new_order
FROM your_table
WHERE color != 'red'
)
UPDATE cte
SET color_order = new_order;

Related

Need to add new column in SQL View and get the value from another row based on condition

There is a table where one of the column stores their local language values and I would like to add another column in SQL view which will have values in English only which we can get it from other country.
here's the sample data
id
country
name
1
Belgium
Product
1
Italy
Prodotto
1
Spain
Product
2
Belgium
Used Car
2
Italy
Usato
2
Spain
Used Car
Expected Results :
id
country
name
English Name
1
Belgium
Product
Product
1
Italy
Prodotto
Product
1
Spain
Product
Product
2
Belgium
Used Car
Used Car
2
Italy
Usato
Used Car
2
Spain
Used Car
Used Car
Please help me with adding new column "English Name" in SQL View which can be derived from other countries. So here, Only Italy will have value other than English so in case Country Italy , I need to get the value from either Beligum/Spain.
Thanks in advance!
You can use the FIRST_VALUE window function to select the name by ordering on when your country is Italy (NULL values are ordered first).
SELECT *, FIRST_VALUE(name) OVER(
PARTITION BY id
ORDER BY CASE WHEN country = 'Italy' THEN 0 END
) AS EnglishName
FROM tab
Check the demo here.

Sum of column depending on values

Can you guys let me know how to make a query that output the sum of amount based on column values(order, Continent and Country)? Also, I want to show all Continent values as unique value (North America)
Example table,
ID Code Continent Country amount
----------------------------------------------------
1 1 North America NULL NULL
2 1 America USA 10
3 1 NA USA 10
4 1 Unknown USA 10
5 2 North America NULL NULL
6 2 America Canada 15
7 2 NA Canada 15
8 2 Unknown Canada 15
9 3 North America NULL NULL
10 3 America Mexico 20
11 3 NA Mexico 20
12 3 Unknown Mexico 20
Output
ID Code Continent Country SumAmount
----------------------------------------------
1 1 North America USA 30
2 2 North America Canada 45
3 3 North America Mexico 60
I have tried to approach it like
select ID, Code, case when Continent != 'North America' then Continent = 'North America' end as Continent, Country, sum(Amount) as SumAmount
from Table group by ID, Continent, Country
or maybe I need to make a query like this and work with this query below?
select ID, Code, Continent, Country, sum(Amount) as SumAmount
from Table where Continent !='North America'
But it is not working. How should I do this?
I appreciate for any other approaches. It would be better than mine
The awkward design here (relations with no real indication of such other than the shared Code column) is going to lead to suboptimal queries like this
DECLARE #ContinentToReport varchar(32) = 'North America';
;WITH x AS
(
SELECT Code FROM dbo.TableName
WHERE Continent = #ContinentToReport
AND Country IS NULL
)
SELECT ID = ROW_NUMBER() OVER (ORDER BY x.Code),
x.Code,
Continent = #ContinentToReport,
t.Country,
SumAmount = SUM(t.amount)
FROM dbo.TableName AS t
INNER JOIN x ON t.Code = x.Code
WHERE t.Country IS NOT NULL
GROUP BY x.Code, t.Country
ORDER BY x.Code;
Output (though I made a guess at what ID means and why it's different then the ID and the source, and I find the Continent column is kind of redundant since it will always be the same):
ID
Code
Continent
Country
SumAmount
1
1
North America
USA
30
2
2
North America
Canada
45
3
3
North America
Mexico
60
Example db<>fiddle
The simplest query which returns the correct result seems to be something like this
select row_number() over (order by Code) ID,
Code,
'North America' Continent,
Country,
sum(amount) SumAmount
from dbo.TableName
where Country is not null
group by Code, Country
order by Code;
dbFiddle

I wonder how it works when multiple group by, like group by column_name(1), column_name(2), column_name(3)

When i checked it, it doesn't remove duplication of value. Why?
example) Group by a , Group by a,b,c
Is there a difference between Group by a, Group by a,b,c ?
I wrote SQL query like this ::
SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country;
result ::
Table: Customers
COUNT(CustomerID) Country
---------------------------------
3 Argentina
2 Austria
2 Belgium
9 Brazil
3 Canada
2 Denmark
2 Finland
to
SELECT COUNT(CustomerID), Country
FROM Customers
GROUP BY Country, CustomerID;
Table: Customers
COUNT(CustomerID) Country
---------------------------------
1 Germany
1 Mexico
1 Mexico
1 UK
1 Sweden
1 Germany
1 France
Why doesn't tie same value changed query from Column_name?
It display all value along column_name.
I wonder if it works. thank you.

Prioritizing Duplicates Based on Criteria

I have a table of data that contains duplicate email addresses. Each email address has a date, a color (values: "Black", "Blue", or "Green"), and a unique ID. There may be sets of duplicate email addresses that contain more than two email addresses (i.e. I may have 10 of duplicates of the same email address) and each set of duplicate email addresses may contain the same or different colors compared to those in its respective duplicate set.
My objective is to retrieve the IDs for email addresses that have a certain color and the max(date). I would like to prioritize the color (first "Black" then "Blue" then "Green") and then move to the max(date) only if there are two or more email addresses within the same duplicate set that have the same highest desired color.
Example 1
ID Email Color Date
1 xyz#xyz.com Black 01/01/2014
2 xyz#xyz.com Black 01/31/2014
3 xyz#xyz.com Blue 03/31/2015
4 xyz#xyz.com Green 01/01/2014
5 xyz#xyz.com Green 01/01/2014
Example 2
ID Email Color Date
6 abc#abc.com Green 12/31/2014
7 abc#abc.com Green 01/01/2014
8 abc#abc.com Blue 01/31/2014
In Example 1, I would want to choose ID 2 as this is the highest desired color of the set of duplicate email addresses--"Black"--and I am choosing the one with max(date).
In Example 2, I would want to choose ID 8 as this is the highest desired color of the set of duplicate email addresses--"Blue".
You can use ROW_NUMBER() to assign priority numbers to each record within every group of duplicate emails as per your requirements. Then, in an outer query, you can select records from each group with the highest priority:
SELECT ID, Email, Color
FROM (
SELECT ID, Email, Color,
ROW_NUMBER() OVER (PARTITION BY email
ORDER BY (CASE Color
WHEN 'Black' THEN 1
WHEN 'Blue' THEN 2
ELSE 3
END),
Date DESC) AS rn
FROM emails ) e
WHERE e.rn = 1
SQL Fiddle Demo

SELECT DISTINCT HAVING Count unique conditions

I've searched for an answer on this but can't find quite how to get this distinct recordset based on a condition. I have a table with the following sample data:
Type Color Location Supplier
---- ----- -------- --------
Apple Green New York ABC
Apple Green New York XYZ
Apple Green Los Angeles ABC
Apple Red Chicago ABC
Apple Red Chicago XYZ
Apple Red Chicago DEF
Banana Yellow Miami ABC
Banana Yellow Miami DEF
Banana Yellow Miami XYZ
Banana Yellow Atlanta ABC
I'd like to create a query that shows the count of unique locations for each distinct Type+Color where the number of unique locations is more than 1, e.g.
Type Color UniqueLocations
---- ----- --------
Apple Green 2
Banana Yellow 2
Note that {Apple, Red, 1} doesn't appear because there is only 1 location for red apples (Chicago). I think I've got this one (but perhaps there is a simpler method). I'm using:
SELECT Type, Color, Count(Location) FROM
(SELECT DISTINCT Type, Color, Location FROM MyTable)
GROUP BY Type, Color HAVING Count(Location)>1;
How can I create another query that lists the Type, Color, and Location for each distinct Type,Color when the count of unique locations for that Type,Color is greater than 1? The resulting recordset would look like:
Type Color Location
---- ----- --------
Apple Green New York
Apple Green Los Angeles
Banana Yellow Miami
Banana Yellow Atlanta
Note that Apple, Red, Chicago doesn't appear because there is only 1 location for red apples. Thanks!
Use a COUNT(DISTINCT Location) and join against a subquery on Type and Color The GROUP BY and HAVING clauses as you have attempted to use them will do the job.
/* Be sure to use DISTINCT in the outer query to de-dup */
SELECT DISTINCT
MyTable.Type,
MyTable.Color,
Location
FROM
MyTable
INNER JOIN (
/* Joined subquery returns type,color pairs having COUNT(DISTINCT Location) > 1 */
SELECT
Type,
Color,
/* Don't actually need to select this value - it could just be in the HAVING */
COUNT(DISTINCT Location) AS UniqueLocations
FROM
MyTable
GROUP BY Type, Color
/* Note: Some RDBMS won't allow the alias here and you
would have to use the expanded form
HAVING COUNT(DISTINCT Location) > 1
*/
HAVING UniqueLocations > 1
/* JOIN back against the main table on Type, Color */
) subq ON MyTable.Type = subq.Type AND MyTable.Color = subq.Color
Here is a demonstration
You could write your first query as this:
Select Type, Color, Count(Distinct Location) As UniqueLocations
From Table
Group By Type, Color
Having Count(Distinct Location) > 1
(if you're using MySQL you could use the alias UniqueLocations in your having clause, but on many other systems the aliases are not yet available as the having clause is evaluated before the select clause, in this case you have to repeat the count on both clauses).
And for the second one, there are many different ways to write that, this could be one:
Select Distinct Type, Color, Location
From Table
Where
Exists (
Select
*
From
Table Table_1
Where
Table_1.Type = Table.Type
and Table_1.Color = Table.Color
Group By
Type, Color
Having
Count(Distinct Location) > 1
)