SQL Boolean expression - sql

I'm new to SQL but I thought naively thought this would be simple.
I have a SQLITE table with FIRSTNAME and LASTNAME columns. I want to exclude specific individuals, e.g. 'Fred Smith' and 'Joe Bloggs'. I used the following:
SELECT FIRSTNAME, SURNAME
FROM MyTable
WHERE (FIRSTNAME != 'Fred' AND LASTNAME != 'Smith');
but that excludes all FIRSTNAMEs = 'Fred' and all LASTNAMEs = 'Smith'. How do I achieve what I need? Secondly, how do I achieve that for multiple individuals, i.e. 'Joe Bloggs' as well as 'Fred Smith'?

How do I achieve what I need?
SELECT FIRSTNAME,SURNAME FROM MyTable WHERE NOT (FIRSTNAME = 'Fred' AND LASTNAME = 'Smith');
or the equivalent
SELECT FIRSTNAME,SURNAME FROM MyTable WHERE (FIRSTNAME != 'Fred' OR LASTNAME != 'Smith');
How do I achieve what I need? Secondly, how do I achieve that for multiple individuals, i.e. 'Joe Bloggs' as well as 'Fred Smith'?
Simply add the relevant AND clause.
SELECT FIRSTNAME,SURNAME FROM MyTable WHERE NOT (FIRSTNAME = 'Fred' AND LASTNAME = 'Smith') AND NOT (FIRSTNAME = 'Joe' AND LASTNAME = 'Bloggs');

Use VALUES to return all the names that you want to exclude and the EXCEPT operator to filter them out:
SELECT FIRSTNAME, LASTNAME FROM MyTable
EXCEPT
VALUES ('Fred', 'Smith'), ('Joe', 'Bloggs');
See the demo.

Related

Function to check for NULL and concatenating the strings

I have a SQL statement that concatenates First Name and Last Name of the person. I use the following SQL statement.
ISNULL(FullName.FirstName, '') + ' ' + ISNULL(FullName.LastName, '')
What I need is to change this to add the FirstName and LastName only if they are not both NULL. If one of them is not NULL, use that value.
Examples:
FirstName and LastName are NULL -> NULL
FirstName is John and LastName is NULL -> John
FirstName is NULL and LastName is Doe -> Doe
-> indicates the result
Use CONCAT() to concatenate without any NULL issues
TRIM() to remove any spaces for when one or both fields are missing
NULLIF() to replace '' with NULL if first and last name are both
missing
SQL Server 2017+ Solution
DROP TABLE IF EXISTS #emp
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = NULLIF(TRIM(CONCAT(FirstName,' ',LastName)),'')
,*
FROM #emp
Actually if you just wrap you current expression inside TRIM() it should give you the behavior you want:
SELECT TRIM(ISNULL(FullName.FirstName, '') + ' ' +
ISNULL(FullName.LastName, '')) AS FullName
FROM yourTable;
In the event that only the first or last name be present, your original expression would leave a dangling leading/trailing space. The call to TRIM() fixes that by removing this extra space.
You can use simple case statement to solve this:
create table emp (emp_id int4, fname varchar(10), lname varchar(10));
insert into emp (emp_id) values(1);
insert into emp (emp_id,fname) values(2, 'John');
insert into emp (emp_id,lname) values(3, 'Doe');
insert into emp (emp_id,fname,lname) values(4, 'John', 'Doe');
select emp_id,fname, lname,
case
WHEN FNAME is not null and LNAME is not null then
FNAME||' '||LNAME
WHEN FNAME is not null and LNAME is NULL then
FNAME
WHEN FNAME is null and LNAME is not NULL then
LNAME
else null
end as FULL_NAME
from emp;
A better SQL Server 2017 solution:
Use the new CONCAT_WS function, which concatenates with a separator, ignoring nulls
CREATE TABLE #emp (ID INT IDENTITY(1,1), FirstName VARCHAR(25), LastName VARCHAR(25));
INSERT INTO #emp
VALUES(null,null)
,('John',null)
,('Doe',null)
,('John', 'Doe');
SELECT FullName = CONCAT_WS(' ', FirstName, LastName)
,*
FROM #emp;
db<>fiddle

Get all results in a single row

When I take a 'SELECT *' query from a table I would like all the results to be displayed in a single 'string' format.
For example:
SELECT * FROM Employees;
Returns:
Id FirstName LastName Age
1 John Smith 30
Instead I would like to get:
Id=1,FirstName=John,LastName=Smith,Age=30
But, if I do exactly the same for the query: SELECT * FROM Cars;
I want this query to adapt and just dynamically gets the columns from the table 'Cars' and do the same with it.
Does one of this select meets your requirements ?
Declare #Employees table(Id integer, FirstName varchar(100), LastName varchar(100), Age integer)
insert into #Employees values (1, 'John', 'Smith', 30), (2, 'John', 'Doe', 23)
select CONCAT('Id=', Id, ', FirstName=', FirstName, ', LastName=', LastName, ', Age=', Age) as Employees from #Employees
select
STUFF ((
select CONCAT('; ', 'Id=', Id, ', FirstName=', FirstName, ', LastName=', LastName, ', Age=', Age) from #Employees
FOR XML PATH('')),1,2, '') as employees
OUTPUT :
Employees
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Id=1, FirstName=John, LastName=Smith, Age=30
Id=2, FirstName=John, LastName=Doe, Age=23
Employees
----------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
Id=1, FirstName=John, LastName=Smith, Age=30; Id=2, FirstName=John, LastName=Doe, Age=23
i don't have the Employees table so i made my own in a variable, but don't mind this, you can test this code without modifying the requests
I want to add that it's code I will use in a trigger, I will be using the 'inserted' and 'deleted' tables. This makes it much harder since I'm not able to use them in a stored procedure.

How to join two columns from same table and format the new Column in SQL

I am very new to SQL and trying to join two columns from the same table and format the result.
The code I have so far is:
Select LastName + FirstName as FullName
from Customers
order by FullName
The columns I am trying to join are LastName, FirstName
The result should be formatted as:
FullName in the following format:
Doe, John
The code should only display results where Last Name is M-Z. Any help is greatly appreciated. I have attached a screenshot below for reference.
https://i.stack.imgur.com/k6qpE.png
You could use calculated column:
CREATE TABLE Customers(LastName NVARCHAR(100), FirstName NVARCHAR(100));
INSERT INTO Customers VALUES ('Doe', 'John'), ('Nagata', 'Naomi');
ALTER TABLE Customers ADD FullName AS (CONCAT(LastName, ', ', FirstName));
Select *
from Customers
where LastName LIKE '[M-Z]%'
order by FullName;
db<>fiddle demo
Select LastName +', '+ FirstName as FullName
from Customers
order by FullName
Try This
Select * from (select Firstname + ' ' + Lastname as Fullname from Students) a order by a.Fullname
Try this:
select
[LastName]+ ', '+[FirstName] as FullName
from [db]
where left([LastName],1) in (
'M',
'N',
'O',
'P',
'Q',
'R',
'S',
'T',
'U',
'V',
'W',
'X',
'Y',
'Z')
order by FullName
;

Transfer Data from One table to Another Table based on a condition

I have a table name SOURCETABLE with fields RollID, SMSID, FName, Lname.
The Destination table is DestTable with field ID, FirstName , LastName.
My task is to creat DestTable from the data of SOURCETABLE with following condition:
If RollID = NULL
ID = SMSID
else
ID = RollID
end if
Fname will go to Firstname and Lname will go to LastName
What statement I should write?
This should do it:
INSERT INTO DestTable (ID, FirstName, LastName)
SELECT COALESCE(RollId,SMSID), FName, LName
FROM SourceTable
You can read about what COALESCE does here:
http://msdn.microsoft.com/en-us/library/ms190349.aspx
INSERT INTO DestTable (Id, FirstName, LastName)
SELECT CASE WHEN ISNULL(RollId,'')='' THEN SMSId ELSE RollId END,
FName, LName FROM SOURCETABLE

SQL SELECT distinct rows from a table by multiple columns ignoring columns order (significance)

I have a table People (First_Name, Last_Name). This table has records that are duplicated as in the example (not all rows are duplicated):
First_Name Last_Name
John Smith
Alec Baldwin
Smith John
Angelo Gordon
Mary Bush
Bush Mary
How do I select all distinct people? In the final output of the query John Smith should appear only once (it’s not import if in the final query there is John Smith or Smith John).
Thank you.
Just pick an ordering and apply it across everyone. Then use a union that will eliminate duplicates anyway
select FirstName,LastName from People where FirstName <= LastName
union
select LastName,FirstName from People where LastName < FirstName
This is one way to do it using pretty much any SQL flavor.
DECLARE #Names TABLE (
First_Name VARCHAR(32)
, Last_Name VARCHAR(32)
)
INSERT INTO #Names VALUES ('John', 'Smith')
INSERT INTO #Names VALUES ('Alec', 'Baldwin')
INSERT INTO #Names VALUES ('Smith', 'John')
INSERT INTO #Names VALUES ('Angelo', 'Gordon')
INSERT INTO #Names VALUES ('Mary', 'Bush')
INSERT INTO #Names VALUES ('Bush', 'Mary')
Using a JOIN
SELECT n1.*
FROM #Names n1
LEFT OUTER JOIN #Names n2 ON n2.First_Name = n1.Last_Name
AND n2.Last_Name = n1.First_Name
AND n2.First_Name < n1.First_Name
WHERE n2.First_Name IS NULL
or NOT EXISTS
SELECT n1.*
FROM #Names n1
WHERE NOT EXISTS (
SELECT *
FROM #Names n2
WHERE n2.First_Name = n1.Last_Name
AND n2.Last_Name = n1.First_Name
AND n2.First_Name < n1.First_Name
)
Sorry was missundertanding your question on the first try...
WITH People (Firstname, Lastname)
AS
(
SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
SELECT 'Alec' AS Firstname, 'Baldwin' AS Lastname UNION
SELECT 'Smith' AS Firstname, 'John' AS Lastname UNION
SELECT 'John' AS Firstname, 'Smith' AS Lastname UNION
SELECT 'Angelo' AS Firstname, 'Gordon' AS Lastname UNION
SELECT 'Mary' AS Firstname, 'Bush' AS Lastname UNION
SELECT 'Bush' AS Firstname, 'Mary' AS Lastname
)
SELECT p1.* FROM People p1
LEFT OUTER JOIN People p2 ON p2.Firstname = p1.Lastname AND p2.Lastname = p1.Firstname AND p2.Firstname < p1.Firstname
WHERE p2.Firstname IS NULL
Here's a solution which uses Oracle functions. Other flavours of SQL will have the same or very similar functions:
SQL> select * from t23
2 /
FIRST_NAME LAST_NAME
------------------------------ ------------------------------
John Smith
Alec Baldwin
Smith John
Angelo Gordon
Mary Bush
Bush Mary
6 rows selected.
SQL> select distinct least(first_name, last_name)
2 , greatest(first_name, last_name)
3 from t23
4 /
LEAST(FIRST_NAME,LAST_NAME) GREATEST(FIRST_NAME,LAST_NAME)
------------------------------ ------------------------------
Alec Baldwin
Bush Mary
John Smith
Angelo Gordon
SQL>
I think this might work in MS-SQL
select * from People
where (FirstName + "," + LastName) <> (LastName + "," + FirstName)
Another sugestion
Temporary Table:
DECLARE #Names TABLE (
First_Name VARCHAR(32)
, Last_Name VARCHAR(32)
)
INSERT INTO #Names VALUES ('John', 'Smith')
INSERT INTO #Names VALUES ('Alec', 'Baldwin')
INSERT INTO #Names VALUES ('Smith', 'John')
INSERT INTO #Names VALUES ('Angelo', 'Gordon')
INSERT INTO #Names VALUES ('Mary', 'Bush')
INSERT INTO #Names VALUES ('Bush', 'Mary')
Using CASE
SELECT DISTINCT
CASE WHEN First_Name <= Last_Name THEN First_Name ELSE Last_Name END AS First_Name,
CASE WHEN First_Name <= Last_Name THEN Last_Name ELSE First_Name END AS Last_Name
FROM #Names