Include a string in Select Query - sql

I'm wondering can we do this query below?
SELECT America, England, DISTINCT (country) FROM tb_country
which will (my intention is to) display :
America
England
(List of distinct country field in tb_country)
So the point is to display (for example) America and England even if the DISTINCT country field returns nothing. Basically I need this query to list a select dropdown, and give some sticky values user can pick, while allowing themselves to add a new country as they wish.
It also goes without saying, that should one row in the tb_country has a value of America or England, they will not show as a duplicate in the query result. So if the tb_country has list of values :
Germany
England
Holland
The query will only output :
America
England
Germany
Holland

You need to use a UNION:
SELECT 'America' AS country
UNION
SELECT 'England' AS country
UNION
SELECT DISTINCT(c.country) AS country
FROM TB_COUNTRY c
UNION will remove duplicates; UNION ALL will not (but is faster for it).
The data type must match for each ordinal position in the SELECT clause. Meaning, if the first column in the first query were INT, the first column for all the unioned statements afterwards need to be INT as well or NULL.

Why you do not add a weight column in tb_country and use a order clause :
Perform once:
update country set weight = 1 where country = 'England';
update country set weight = 1 where country = 'America';
Then use it:
select distinct(country) from tb_country order by desc weight ;
Another way is to use an extra country table with two columns (country, weight) and an outer join.
Personnaly I rather prefer a country table with a UNIQUE constraint for country field and
Use of a foreign key.

Related

SQL Function Get Column By Reference

Let's say there are 3 tables: Genders, Countries and Users. Users has among others a column named Gender and also a column named Country.
I want to add a new entry to Users and select one of the columns Male/Female {M, F} and a country from the rows of Countries dynamically just for testing purposes.
insert into dbo.[Users] (Gender, UserName, Country)
select Genders.Male, 'newbie', Countries.(the one which matches column CountryId) FROM Genders, Countries
I want to achieve this: 'M', 'newbie', MyCountry
After applying the suggestion from 'zip' I get the result 2 rows affected, same number as the external tables I'm referencing. The Query added 2 rows, so I guess I am missing the WHERE conditions.
The Genders Table is meant as a Property and will have only one row that I manually added.
Table Genders; 1 row
Male : uniqueidentifier
Female : uniqueidentifier
Countries is a table with many rows, so I want to select one matching the criteria of one of it's column values, say the value of column CountryId.
You can get a random value using:
insert into dbo.[Users] (Gender, UserName)
select top (1) g.Male, 'newbie'
from Genders.Male
order by newid();
I figuored the solution out. Thank you all who responded for pointing me in the right direction.
INSERT INTO dbo.[Users] (Gender, UserName, Country)
SELECT Genders.Male, 'newbie', Countries.CountryId
FROM Genders, Countries
WHERE Countries.ISO2 = '##'
'##' = 2 letter ISO of country.
Explanation:
1. INSERT INTO dbo.[Users] = Add a new row to Table "Users"
2. (Gender, UserName, Country) = Includes the columns in table "Users". If a column is not specified and it had a property of not allowing Nulls, an exception would be thrown!
3. FROM Genders, Countries = Include the external tables associated to look for
4. WHERE Countries.ISO2 = '##' = This condition allows you to precisely select which column of which row you seek. So I searched for a certain row where a column named ISO2 had a value '##' and looked then for the CountryId value in the same row (entry). There may be cases when multiple rows have identical value so you would have to further specify the conditions by using AND or OR oeprators.
When a table does not contain more than 1 row, I should not have to apply WHERE Conditions. It will select the default one existing. But because the Countries Table had multiple items (3 Rows), leaving the WHERE clause out, caused to add 3 times the same User, with each row having a distinct CountryId!

SQL combine 2 rows into 1 row then delete 1

I'm trying to complete an SQL query homework question and cannot figure out how to add 2 rows together from the same table, with the intention of deleting one after they are combined.
I have a table name 'country', in it, I have 241 rows of data with columns.
name region area population GDP
------------------------------------------------------------------------
Hong Kong Southeast Asia 1040 5542869 136100000000
China Asia 9596960 1203097268 2978800000000
Expected output:
name region area population GDP
-------------------------------------------------------------------
Hong Kong Southeast Asia 1040 5542869 136100000000
China Asia 9598000 1208640137 3114900000000
The goal is to keep the name of the row as "China" and the region as "Asia" but adding the numeric values from the "Hong Kong" row to the "China" row for the columns (area, population, and GDP).
I have tried UNION and MERGE but I'm not familiar with using them and couldn't get it to work.
I feel like it has to be something like the SQL query below:
update country
set area = area.HongKong + area.China
where name = 'China';
but I don't know the proper way to reference a specific row.
Ah yes, homework. I remember those days.
Here is some code to help out -
--create a temp table to hold sample data
select
*
into #country
from
(
values
('Hong Kong', 'Southeast Asia', 1040, 5542869, 136100000000),
('China', 'Asia', 9596960, 1203097268, 2978800000000),
('USA', 'North America', 1, 10, 100) --some other row in table
) d ([name], region, area, population, gdp);
select * from #country;
Here is what the data looks like in this table:
--update statement
with
Totals as
(
select
count(1) rows, --should be 2
sum(area) areaTotal,
sum(population) populationTotal,
sum(gdp) gdpTotal
from #country
where [name] in ('Hong Kong', 'China') --this filter may be insufficient; it would be better to select by a primary key such as a rowID but the table does not have one
)
update c
set c.area = t.areaTotal,
c.population = t.populationTotal,
c.gdp = t.gdpTotal
from #country c
inner join totals t
on c.[name] = 'China';
Here is what the data looks like after the update:
There are a few noteworthy things here:
The code above the update statement, with Totals as (..., is called a common table expression (also abbreviated as CTE). It is being used here to contain the query that calculates the totals needed to perform the update. A CTE is one approach to creating an intermediate data set. Alternative approaches to this include: creating a temp table or using a derived table.
To see the results of the query within the CTE, those lines of code can be highlighted in your editor and executed against the database.
The original post said there are 241 rows of data in the country table. This means it is important to have a reliable filter in the query that calculates the totals so the correct rows for summing are isolated. The preferred way to filter the rows is to use a primary key, such as a rowID. Since this table does not have a primary key column, I made a guess and used the [name] column.
The purpose of count(1) rows in the CTE is to make sure only 2 rows are being summed. If this number comes back as anything other than 2, it means there is a problem with the filter and the where clause needs to be modified. The number of rows will only be visible when you do #2 above.
Now the Hong Kong row needs to be cleaned up:
--delete old row
delete from #country where [name] = 'Hong Kong';
This is what the data looks like now:
Again, it would be preferable to use a primary key column in the where clause instead of the [name] column to be certain that the correct row is being deleted.

Count distinct query MS Access

It seems that we can not use Count (Distinct column) function in MS Access. I have following data and expected result as shown below
Looking for MS Access query which can give required result.
Data
ID Name Category Person Office
1 FIL Global Ben london
1 FIL Global Ben london
1 FIL Overall Ben Americas
106 Asset Global Ben london
156 ICICI Overall Rimmer london
156 ICICI Overall Rimmer london
188 UBS Overall Rimmer london
9 Fund Global Rimmer london
Expected Result
Person Global_Cnt Overall_Cnt
Ben 2 1
Rimmer 1 2
Use a subquery to select the distinct values from your table.
In the parent query, GROUP BY Person, and use separate Count() expressions for each category. Count() only counts non-Null values, so use IIf() to return 1 for the category of interest and Null otherwise.
SELECT
sub.Person,
Count(IIf(Category = 'Global', 1, Null)) AS Global_Cnt,
Count(IIf(Category = 'Overall', 1, Null)) AS Overall_Cnt
FROM
(
SELECT DISTINCT ID, Category, Person
FROM YourTable
) AS sub
GROUP BY sub.Person;
I was unsure which fields identify your unique values, so chose ID, Category, and Person. The result set from the query matches what you asked for; change the SELECT DISTINCT field list if it doesn't fit with your actual data.
When creating a query in Microsoft Access, you might want to return only distinct or unique values. There are two options in the query's property sheet, "Unique Values" and "Unique Records":
DISTINCT and DISTINCTROW sometimes provide the same results, but there are significant differences:
DISTINCT
DISTINCT checks only the fields listed in the SQL string and then eliminates the duplicate rows. Results of DISTINCT queries are not updateable. They are a snapshot of the data.
DISTINCT queries are similar to Summary or Totals queries (queries using a GROUP BY clause).
DISTINCTROW
DISTINCTROW, on the other hand, checks all fields in the table that is being queried, and eliminates duplicates based on the entire record (not just the selected fields). Results of DISTINCTROW queries are updateable.
Read More...
MS Access-Engine does not support
SELECT count(DISTINCT....) FROM ...
You have to do it like this:
SELECT count(*)
FROM
(SELECT DISTINCT Name FROM table1)
Its a little workaround... you're counting a DISTINCT selection.
select count(column) as guessTable
from
(
select distinct column from Table
)

Joining Three tables without a matching column

I want to create a geography dimension using ssis 2008.I have 3 table sources.
Here is the explanation
Table 1 = Country: country code and country name
Table 2 = Post code: post code and city name
Table 3 = Territory : Territory code and Territory name
Here is how data looks
[Table 1= Country]
code name
------------------
US | United states
CA | Canada
[Table 2= post code]
Code city
---------------
1000 | Paris
2000 | Niece
[Table 3= Territory]
Code name
----------------
N | North
S | south
As you can see there is no single common column, I want to group these 3 tables in the same geography dimension.
So, how can I do it ?
Also,The use of this geography dim will be when another dimension for example customer dimension.we want to know the revenue of client according to his geography or the the top salespersons in some city.
and in both customer and salesperson tables you can find the those 3 as foreign keys.
You don't need a "common column" shared by all three tables.
You do need a "column column" between each pair of tables. How else are you going to link them???
Q: Is there any column that links "Country" to "City"? You should have a "country code" column in "city".
Q: Is there any way to link "Territory" with either "post code" or "country"? If "Yes": problem solved. Please list the fields. If "No" ... then you need to change your schema.
Based on you comment to paulsm4 you then want to use those tables that hold the linking information to join to each of the above 3 tables.
On the other hand if you really want to join just those three tables
select * from Country
full outer join [Post code]
on 'a' = 'a'
full outer join Territory
on 'b' = 'b'
create table dim.geography (geoID int,citycode int, countrycode char(2),territorycode char(1))
insert into dim.geography (select city as citycode,country as countrycode, territory as territorycode from Customer union select city, country,territory from salesperson)
Assuming here that Customer and salesperson tables hold the codes and not the values for country,territory, and country.
The code above will build a dimension for the geography you want. Of course if you add any additional unique city,country,territory codes into the customer/salesperson tables you will need to add it to your dimension. This is just an initial load. You may also need to modify the code to account for nulls in any of the three qualifiers.

Mysql, reshape data from long / tall to wide

I have data in a mysql table in long / tall format (described below) and want to convert it to wide format. Can I do this using just sql?
Easiest to explain with an example. Suppose you have information on (country, key, value) for M countries, N keys (e.g. keys can be income, political leader, area, continent, etc.)
Long format has 3 columns: country, key, value
- M*N rows.
e.g.
'USA', 'President', 'Obama'
...
'USA', 'Currency', 'Dollar'
Wide format has N=16 columns: county, key1, ..., keyN
- M rows
example:
country, President, ... , Currency
'USA', 'Obama', ... , 'Dollar'
Is there a way in SQL to create a new table with the data in the wide format?
select distinct key from table;
// this will get me all the keys.
1) How do I then create the table using these key elements?
2) How do I then fill in the table values?
I'm pretty sure I can do this with any scripting language (I like python), but wanted to know if there is an easy way to do this in mysql. Many statistical packages like R and STATA have this command built in because it is often used.
======
To be more clear, here is the desired input output for a simple case:
Input:
country attrName attrValue key (these are column names)
US President Obama 2
US Currency Dollar 3
China President Hu 4
China Currency Yuan 5
Output
country President Currency newPkey
US Obama Dollar 1
China Hu Yuan 2
Cross-tabs or pivot tables is the answer. From there you can SELECT FROM ... INSERT INTO ... or create a VIEW from the single SELECT.
Something like:
SELECT country,
MAX( IF( key='President', value, NULL ) ) AS President,
MAX( IF( key='Currency', value, NULL ) ) AS Currency,
...
FROM table
GROUP BY country;
If you were using SQL Server, this would be easy using UNPIVOT. As far as I am aware, this is not implemented in MySQL, so if you want to do this (and I'd advise against it) you'll probably have to generate the SQL dynamically, and that's messy.
I think I found the solution, which uses VIEWS and INSERT INTO (as suggested by e4c5).
You have to get your list of AttrNames/Keys yourself, but MYSQL does the other heavy lifting.
For the simple test case above, create the new_table with the appropriate columns (don't forget to have an auto-increment primary key as well). Then
CREATE VIEW a
AS SELECT country, attrValue
WHERE attrName="President";
CREATE VIEW b
AS SELECT country, attrValue
WHERE attrName="Currency";
INSERT INTO newtable(country, President, Currency)
SELECT a.country, a.attrValue, b.attrValue
FROM a
INNER JOIN b ON a.country=b.country;
If you have more attrNames, then create one view for each one and then adjust the last statement accordingly.
INSERT INTO newtable(country, President, Currency, Capital, Population)
SELECT a.country, a.attrValue, b.attrValue, c.attrValue, d.attrValue
FROM a
INNER JOIN b ON a.country=b.country
INNER JOIN c ON a.country=c.country
INNER JOIN d ON a.country=d.country;
Some more tips
use NATURAL LEFT JOIN and you don't have to specify the ON clause