Getting Duplicate results when using INNER JOIN - sql

I have 3 tables. One with user names, one with a bunch of data, and then one that links the 2 tables together via their ID's. When I try and join the 3 with an INNER JOIN, I get a bunch of duplicate rows. For example, if the data table only has 2000 rows, once I try and use the inner join to connect the 3 tables, I get an output that shows 100,000 rows. Does this have something to do with the fact that my Data table has more rows than my User name table and the inner join doesn't play nicely? Is it possible to inner join one table that has more rows than the other?
EDIT FOR CLEARITY
For this database I import data that looks something like this:
-Names-----------Numbers-----------Item---------------Cost---
John Smith 111-1111 Pencils 100.75
Joe Stevens 222-2222 Paper 35.34
Mike Jones 333-3333 Staples 23.86
John Smith 111-1111 Boxes 11.76
As you can see John Smith is listed twice, for two separate items. I would like to optimize this, but separating the original data and putting things in their own table with only one iteration.
ID---Name--- ID----Numbers ID---Items------Cost
1 John Smith 1 111-1111 1 Pencil 100.75
2 Joe Stevens 2 222-2222 2 Paper 35.34
3 Mike Jones 3 333-3333 3 Staples 23.86
4 Boxes 11.76
Now that things are optimized, I need to be able to still run a query that could match John Smith with both the pencils and the boxes. This is why I created the link table that holds the IDs in the correct sequence they need to be in.
Name.ID Number.ID Item.ID
1 1 1
2 2 2
3 3 3
1 1 4
Now if I wanted to run a report that recreates the original data dump, I would run a query that just joins the 3 tables with an inner join. The issue though, is that I'm getting results with tons of duplicates, rather than just simply outputting that data as it should be. I get something like this:
-Names-----------Numbers-----------Item---------------Cost---
John Smith 111-1111 Pencils 100.75
John Smith 111-1111 Pencils 100.75
John Smith 111-1111 Pencils 100.75
John Smith 111-1111 Pencils 100.75
John Smith 111-1111 Pencils 100.75
Joe Stevens 222-2222 Paper 35.34
Joe Stevens 222-2222 Paper 35.34
Joe Stevens 222-2222 Paper 35.34
Joe Stevens 222-2222 Paper 35.34
Mike Jones 333-3333 Staples 23.86
Mike Jones 333-3333 Staples 23.86
Mike Jones 333-3333 Staples 23.86
Mike Jones 333-3333 Staples 23.86
John Smith 111-1111 Boxes 11.76
John Smith 111-1111 Boxes 11.76
John Smith 111-1111 Boxes 11.76
John Smith 111-1111 Boxes 11.76
The desired output would simply be:
-Names-----------Numbers-----------Item---------------Cost---
John Smith 111-1111 Pencils 100.75
Joe Stevens 222-2222 Paper 35.34
Mike Jones 333-3333 Staples 23.86
John Smith 111-1111 Boxes 11.76

try this one
Select Distinct t1.Names,t2.Number,t3.Item,t3.Cost
From
tableName t1
inner join tableNum t2
on t1.ID = t2.ID
inner join tableItem t3
on t1.ID = t3.ID

Related

Add columns to table based on other rows and columns

For example, I have the following table in SQL Server:
name
from
to
traveling date
Mike
london
Paris
5/jan/2022
Mike
Paris
Barcelona
5/jan/2022
Sam
Cairo
Riyadh
6/Mar/2022
Sam
Riyadh
Dubai
6/Mar/2022
Sam
Dubai
Maldives
7/Mar/2022
Sam
Maldives
Riyadh
13/Mar/2022
Sam
Riyadh
Cairo
13/Mar/2022
And the result I want must have new columns based on other columns and rows, like below:
name
from
to
traveling date
Route
Date
Mike
London
Paris
5/Jan/2022
London-Barcelona
5/Jan/2022
Mike
Paris
Barcelona
5/Jan/2022
Sam
Cairo
Riyadh
6/Mar/2022
Cairo-Maldives
6/Mar/2022
Sam
Riyadh
Dubai
6/Mar/2022
Sam
Dubai
Maldives
7/Mar/2022
Sam
Maldives
Riyadh
13/Mar/2022
Maldives-Cairo
13/Mar/2022
Sam
Riyadh
Cairo
13/Mar/2022
As you can see Sam had Round ticket he reached the next day of traveling and stayed for couple of days in Maldives.
All I care about is to consider Route as 1 ticket and have the traveling date from 'Date'.
Help please.

How can I sort a table by two columns in sisense?

I use Sisense Version: 20.21.6.10054 on Windows.
I need to sort a table widget in sisense by two columns, first by name, and second by number of behavior that person demonstrates.
The result should look like this:
id first_name last_name behavior_NO behavior_link
1 Ben Smith 1 behavior_1
1 Ben Smith 2 behavior_2
1 Ben Smith 3 behavior_3
2 Sam Johns 1 behavior_1
2 Sam Johns 2 behavior_2
3 Martha Star 1 behavior_1
3 Martha Star 2 behavior_2
3 Martha Star 3 behavior_3
3 Martha Star 4 behavior_4
Now, when I sort by Last_name the behavior_No is not sorted in correct order, but it looks like this:
id first_name last_name behavior_NO behavior_link
1 Ben Smith 1 behavior_1
1 Ben Smith 3 behavior_3
1 Ben Smith 2 behavior_2
2 Sam Johns 2 behavior_2
2 Sam Johns 1 behavior_1
3 Martha Star 4 behavior_4
3 Martha Star 2 behavior_2
3 Martha Star 1 behavior_1
3 Martha Star 3 behavior_3
Sisense does not allow to sort by two columns in a table.
I tried to pivot the table but the problem is that there is a column with hyperlinks in it, and when making a pivot hyperlinks display like a text (<a href="https://https://stackoverflow.com/ ) but not like a link.
Can anyone advise on how to solve this, either to sort the table by two columns or to insert a hyperlink in a pivot?
Thanks in advance.
Maybe you already find a better way that the following but yesterday I had a requested to do a rank but also, ordering three columns. First I needed order by the Target then by Rank and then by Sales so in the pivot table can look like this:
Sales_Person | Target | Sales | Rank
Joe | 100% | 12 | 1
Chris | 100% | 12 | 1
Maria | 98% | 11 | 2
Peter | 97% | 10 | 3
So because Sisense in the front end does not allow to sort two or more columns there is a built-in function called "ORDERING".
In the following link you will find the function under "Other Functions"
Function References Sisense
The only disadvantage is that at the time you implement this function it will create an additional column for ordering so at the end I obtained the following results:
Sales_Person | Target | Sales | Rank | Ordering
Joe | 100% | 12 | 1 | 0
Chris | 100% | 12 | 1 | 1
Maria | 98% | 11 | 2 | 2
Peter | 97% | 10 | 3 | 3
Also, keep in mind that all the different columns should be dimensions.
By the way, the version I have is Sisense L2022.4.0.222

assign an existing id value to same record and new id to new record

I'm trying to see if I can assign an id to a name every time that same record comes in. For instance, if I assign an ID E001 to John Doe, I want to be able to assign that same value to John every time I see a record of John. And if a new person comes into the picture, I want to pick the next ID from a list I created (table ID) and assign it to that person and so on. I'm open to suggestions or ideas or better ways on how to go about doing it either SQL (preferably) or some ETL approach. Thanks
Month 1 file (or another table in oracle)
Name Addr Location
------------------------------
John Doe 123 Main NA
John Doe 123 Main NA
Bob Lava 456 Tel US
ORACLE_TABLE in month 1
ID Name Addr Location
-------------------------------------
E001 John Doe 123 Main NA
E001 John Doe 123 Main NA
E002 Bob Lava 456 Tel US
Month 2 files (or oracle table)
Name Addr Location
-------------------------------
Denny Fry 456 str AB
John Doe 123 Main NA
John Doe 123 Main NA
Bob Lava 456 Tel US
ORACLE TABLE in month 2 (simply append month 2 files to existing data but using previously assigned ID for existing records and a new id for a new record)
ID Name Add Location
------------------------------------
E001 John Doe 123 Main NA
E001 John Doe 123 Main NA
E002 Bob Lava 456 Tel US
E003 Denny Fry 456 str AB
E001 John Doe 123 Main NA
E001 John Doe 123 Main NA
E002 Bob Lava 456 Tel US
ID table list (used to assign IDs to records)
E001
E002
E003
E004
B001
I can suggest a SQL solution in which first do union all and then you can use dense_rank() as following
select
Name,
Addr,
Location,
'E00' || dense_rank() over (order by Name) as EmpId
from
(
select
Name,
Addr,
Location
from monthOne
union all
select
Name,
Addr,
Location
from monthTwo
) val
order by
EmpId
output:
*-----------------------------------*
| NAME ADDR LOCATION EMPID |
*-----------------------------------*
|Bob Lava 456 Tel US E001 |
|Bob Lava 456 Tel US E001 |
|Denny Fry 456 str AB E002 |
|John Doe 123 Main NA E003 |
|John Doe 123 Main NA E003 |
|John Doe 123 Main NA E003 |
|John Doe 123 Main NA E003 |
*-----------------------------------*

SQL exercise using a self Left Outer Join

This is the exercise:
How can you output a list of all members, including the individual who recommended them (if any)? Ensure that results are ordered by (surname, firstname).
The solution is below only I don't understand why it's 'ON recs.memid = mems.recommendedby' and not 'mems.memid = recs.recommendedby'. Why doesn't the latter work? I want to correct my thinking on how to use a Left Outer Join to itself.
CREATE TABLE members (
memid SERIAL PRIMARY KEY,
firstname VARCHAR(20),
surname VARCHAR(20),
recommendedby INTEGER References members(memid)
);
SELECT
mems.firstname AS memfname,
mems.surname AS memsname,
recs.firstname AS recfname,
recs.surname AS recsname
FROM
cd.members AS mems
LEFT OUTER JOIN cd.members AS recs
ON recs.memid = mems.recommendedby
ORDER BY memsname, memfname;
Consider this data:
MEMID | FIRSTNAME | SURNAME | RECOMMENDEDBY
------|-----------|---------|--------------
1 | John | Smith | null
2 | Karen | Green | 1
3 | Peter | Jones | 1
Here John recommended both Karen and Peter, but no one recommended John
'ON recs.memid = mems.recommendedby' (The one that "works")
You're getting a list of members and the ones that recommended them. Any member can only have been recommended by one member as per the table structure, so you'll get all the members just once. You're taking the recommendedby value and looking for it in the memid column in the "other table":
recommendedby --|--> memid of members that recommended them
MEMID | FIRSTNAME | SURNAME | RECOMMENDEDBY
------|-----------|---------|--------------
Karen | Green | John | Smith
Peter | Jones | John | Smith
John | Smith | null | null
The recommendedby column only has John (1), so when looking for the value 1, John comes up.
'ON mems.memid = recs.recommendedby' (The one that doesn't work)
You'll again get all the members. But here you're getting them as the ones doing the recommending, so to say. If they didn't recommend anyone, the paired record will be blank. This is because you're taking the memid value and looking to see if it matches the recommendedby column of the "other table". If a member recommended more than one, the record will appear multiple times:
memid --|--> recommendedby
MEMID | FIRSTNAME | SURNAME | RECOMMENDEDBY
------|-----------|---------|--------------
Karen | Green | null | null
Peter | Jones | null | null
John | Smith | Karen | Green
John | Smith | Peter | Jones
Karen and Peter didn't recommend anyone, but John recommended both the others.

Retrieve value from column depending on another column

From this table of football players, how would you select the players' names alongside their captains' names?
PlayerID | PlayerName | TeamCaptainID
=====================================
1 | Jay | 5
2 | John | 3
3 | James | 3
4 | Jack | 5
5 | Jeremy | 5
The result I'm after is:
Player | Captain
================
Jay | Jeremy
John | James
James | James
Jack | Jeremy
Jeremy | Jeremy
Applying inner join on the same table seems to be enough:
select t1.PlayerName as Player
, t2.PlayerName as Captain
from tbl t1
join tbl t2 on t1.TeamCaptainID = t2.PlayerID
To find the exact result you want, you have to use self-join, it is how this will work:
To achieve the desired outcome, we will use the same table twice and in order to do this we will use the alias of the table, a self join must have aliases.
To get the list of Players and their captain the following sql statement can be used :
SELECT a.PlayerName AS "Player",
b.TeamCaptainID AS "Captain"
FROM team a, team b
WHERE a.TeamCaptainID=b.PlayerName