PostgreSQL Query Not Returning Data - sql

I have 2 tables (tabl1 and tbl2) and I want a query that joins tbl2 to tbl1 by matching its col1id and col2id so that the result set contains the tbl1 data with the name column in tbl2.
The following query returns no data:
SELECT Date
,cast(tbl1.col1_id as varchar) AS "col1name"
,tbl2.name::varchar AS "tabl2name"
,tbl1.currency::money as "Avg currency"
,CASE WHEN rich IS NULL then 'Unknown'
ELSE 'True' END AS "bank"
,CAST(Ranking AS FLOAT) / 18 + 1 AS "Rich Ranking"
,tbl1.Reviews as "Reviews"
FROM tbl1
JOIN tbl2
ON tbl1.col1id = tbl2.col2id
tbl1.col1id contains numbers like 3,999,999
When I do a full right join, I am able to get the all the data from the 2 separate tables
I created a new table with certain names I wanted next to it.
I created a new table with values with the exact match of the 3,999,999 and I am getting no matches in the end so I thought types were at fault and I've been messing around with the data a bit and I'm stuck.
I am guessing the values are not the same type, so I did some extra work inputting it either as integer or varchar elsewhere and on the same query.
But the results returned as nothing but did not generate an error so I believe it's a type error on my end.

If you just wanna to do what you describe in your post, better avoid unnecessary complexity. Does the following return anything?
SELECT tbl1.*, tbl2.name
FROM tbl1
JOIN tbl2
ON tbl1.col1id = tbl2.col2id;
If nothing comes back I would first suggest to check if there are any tbl2.col2id that match tbl1.col1id at all.
You could do that easily by using a LEFT JOIN (atm by using JOIN you are using an INNER JOIN really). Your rowset would then contain all rows from tbl1 and have null values in tbl2.name if no join was possible.
Apart from that i would make sure that the datatypes of tbl1.col1id and tbl2.col2id are the same.

Related

Sql server query with CTE containing CLR returns empty string after joining to more than 5 tables

Kind of a weird one.
I have a CTE, it selects 3 columns. and id, then two varchar fields. The varchar fields use a CLR function to concatenate names with a '/' dividing them.
I run this query on 5 environments and on 4 of them it returns the names with the '/'.
On the other environment, it's empty string (all enviros/servers have same copy of db).
Running the CTE body returns data fine on all environments.
In commenting out sections of the sql, data is returned fine until I join to more than 5 tables (even if the table has nothing to do with the query). Just seems that no matter what table I join to, after 5 joins my varchar data becomes empty string. If I filter out for a specific id, data is returned fine.
Im guessing there's some sort of environment config that's different on the one environment compared to the others. Anyone have any idea?
with my_cte as
(
select my_id,
dbo.List(names1, '/') names1,
dbo.List(names2, '/') names2
from table
where blah= blah
)
select A.some_field,
OU.names1,
OU.names2
from myTable A
inner join my_cte OU on (OU.this_id = A.this_id)
inner join table3
inner join table4
inner join table5
inner join table6 --once i get here, no matter what table6 is, the names1, names2 become empty string
where A.blah = xxxx;
Quick fix was to rewrite the CTE into a temp table until dba's check the config diffs between the boxes. Thanks for the comments.

How to merge data from two tables with some common fields

So I have two tables that have similar data. There are columns in table A that match columns in table B, but with different naming conventions, there are also columns from each that have no equivalent in the other table, no rows should be merged, I need a view (I think) with all the rows from both tables, but with some columns merged so that data from table A.columnB and data from table B.columnF both end up in view C.columnD. There would be columns in the view that only had sources in one of the tables and would be null in rows from the other table. I can't change any of the existing table structure as the database is shared across multiple apps. I think I need to use a bunch of FULL OUTER JOIN statements in the view but I'm having trouble wrapping my mind around how to really go about it. If anyone can provide a generic example of how this should look I should be able to take it from there.
Here's an example of what doesn't work (there are a lot more columns on each side of the JOIN in the actual db, truncated for readability):
SELECT
schedule_block.id as vid,
schedule_block.reason as vreason,
schedule_block.when_ts as vwhen,
schedule_block.duration as vduration,
schedule_block.note as vnote,
schedule_block.deleted_ts as vdeleted_when,
schedule_block.deleted_user_id as vdeleted_user_id,
schedule_block.lastmodified_ts as vlastmodified_ts,
schedule_block.lastmodified_user_id as vlastmodified_user_id
FROM schedule_block
FULL OUTER JOIN appointment.appt_when as vwhen ON 1 = 1
FULL OUTER JOIN appointment.patient_id as vpatient ON 1 = 1
FULL OUTER JOIN appointment.duration as vduration on 1 = 1
FULL OUTER JOIN appointment.deleted_when as vdeleted_when ON 1 = 1
Correct me if I'm wrong but I think I can't use a UNION because there are different numbers of columns on each side
You could do something like:
SELECT ColA, CONVERT(DATE, NULL) AS ColB
FROM T1
UNION ALL
SELECT CONVERT(VARCHAR(10), NULL) AS ColA, ColB
FROM T2
Just make sure to match the datatypes.

Convert columnB value if columnA = X in SQL

Overview
I have an inner join statement that links 5 tables together which is working fantastically if i do say so myself.
Now one of the values returned is in Hex and it is in a column named Value however, the Value column also contains other values and so i cannot simply convert the whole column.
Every Hex entry into column Value has an identifier of 18 in a column called DataTypeID.
The Question
How can i convert just the Hex entry in column Value if DataTypeID=18.
I know this needs a function with:
SELECT CONVERT(INT, CONVERT(VARBINARY
But I am unsure of how to write it and where to place it, is it before my inner join statement or after?
SELECT Data.Value AS Value, Entry_Data.DataTypeID AS DataTypeID
From Database.Entry
INNER JOIN Database.Data on Entry_Data.DataTypeID=DataTypeID
INNER Join Database.Data on Data.Value=Value
Please note that this is not an accurate example of the script its just for example purposes
Now i assume that i would create my function above this query and then add a where function below it.
The names of the columns and identifier are accurate.
You can use the case expression.
Your query is a little difficult to interpret intent, so I am going to make an assumption that you have two tables, (TableA and TableB) and you want to join one to the other like this: TableA.Value = TableB.Value, but TableB stores its Value column as a mixture of ints and hex(ints) where the hex(insts) are identified by value of TableB.VDataTypeID = 18 and anyt other DataTypeID indicates that TableB.Value a regular int.
If this is the case, to the following:
SELECT
...
FROM
TableA
INNER JOIN TableB ON TableA.Value
= CASE WHEN TableB.DataTypeID = 18 THEN Convert(...
ELSE TableB.DataTypeID
END
So you are using the CASE expression effectively as an in-place function on which to join.
It reads, Join TableA to TableB on the Values directly if TableB.DataTypeID is not 18, but if it is 18, then convert TableB.Value first and then do the join.
Hope this gives you what you need :-)

Number of Records don't match when Joining three tables

Despite going through every material I could possibly find on the internet, I haven't been able to solve this issue myself. I am new to MS Access and would really appreciate any pointers.
Here's my problem - I have three tables
Source1084 with columns - Department, Sub-Dept, Entity, Account, +few more
R12CAOmappingTable with columns - Account, R12_Account
Table4 with columns - R12_Account, Department, Sub-Dept, Entity, New Dept, LOB +few more
I have a total of 1084 records in Source and the result table must also contain 1084 records. I need to draw a table with all the columns from Source + R12_account from R12CAOmappingTable + all columns from Table4.
Here is the query I wrote. This yields the right columns but gives me more or less number of records with interchanging different join options.
SELECT rmt.r12_account,
srb.version,
srb.fy,
srb.joblevel,
srb.scenario,
srb.department,
srb.[sub-department],
srb.[job function],
srb.entity,
srb.employee,
table4.lob,
table4.product,
table4.newacct,
table4.newdept,
srb.[beg balance],
srb.jan,
srb.feb,
srb.mar,
srb.apr,
srb.may,
srb.jun,
srb.jul,
srb.aug,
srb.sep,
srb.oct,
srb.nov,
srb.dec,
rmt.r12_account
FROM (source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account)
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity )
WHERE ( ( ( srb.[sub-department] ) = table4.subdept )
AND ( ( srb.entity ) = table4.entity )
AND ( ( rmt.r12_account ) = table4.r12_account ) );
In this simple example, Table1 contains 3 rows with unique fld1 values. Table2 contains one row, and the fld1 value in that row matches one of those in Table1. Therefore this query returns 3 rows.
SELECT *
FROM
Table1 AS t1
LEFT JOIN Table2 AS t2
ON t1.fld1 = t2.fld1;
However if I add the WHERE clause as below, that version of the query returns only one row --- the row where the fld1 values match.
SELECT *
FROM
Table1 AS t1
LEFT JOIN Table2 AS t2
ON t1.fld1 = t2.fld1
WHERE t1.fld1 = t2.fld1;
In other words, that WHERE clause counteracts the LEFT JOIN because it excludes rows where t2.fld1 is Null. If that makes sense, notice that second query is functionally equivalent to this ...
SELECT *
FROM
Table1 AS t1
INNER JOIN Table2 AS t2
ON t1.fld1 = t2.fld1;
Your situation is similar. I suggest you first eliminate the WHERE clause and confirm this query returns at least your expected 1084 rows.
SELECT Count(*) AS CountOfRows
FROM (source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account)
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity );
After you get the query returning the correct number of rows, you can alter the SELECT list to return the columns you want. But the columns aren't really the issue until you can get the correct rows.
Without knowing your tables values it is hard to give a complete answer to your question. The issue that is causing you a problem based on how you described it. Is more then likely based on the type of joins you are using.
The best way I found to understand what type of joins you should be using would referencing a Venn diagram explaining the different type of joins that you can use.
Jeff Atwood also has a really good explanation of SQL joins on his site using the above method as well.
Best to just use the query builder. Drop in your main table. Choose the columns you want. Now for any of the other lookup values then simply drop in the other tables, draw the join line(s), double click and use a left join. You can do this for 2 or 30 columns that need to "grab" or lookup other values from other tables. The number of ORIGINAL rows in the base table returned should ALWAYS remain the same.
So just use the query builder and follow the above.
The problem with your posted SQL is you NESTED the joins inside (). Don't do that. (or let the query builder do this for you – they tend to be quite messy but will also work).
Just use this:
FROM source1084 AS srb
LEFT JOIN r12caomappingtable AS rmt
ON srb.account = rmt.account
LEFT JOIN table4
ON ( srb.department = table4.dept )
AND ( srb.[sub-department] = table4.subdept )
AND ( srb.entity = table4.entity )
As noted, I don't see why you are "repeating" the conditions again in the where clause.

Joining two tables on colums with dissimilar (but connected) values

How can I connect two tables on columns with certain linked values but not having the same values?
For instance I need to join tbl1 to tbl2 where tbl1.col=100 and tbl2.col=200. The only connection that have is to me/my company.
Is there a way to link the rows without an explicit shared value? I need all rows with col value '100' to be on the same row as all tbl2 columns have col value 200.
You can put some logic in your join predicate, as in:
select *
from tbl1 as a
join tbl2 as b on a.col + 100 = b.col
Is there a way to link the rows without an explicit shared value?
Yes. You can write a custom JOIN to relate data yourself.
You didn't specify your specific DBMS, so the following examples contain generic SQL.
SELECT * FROM tbl1, tbl2 WHERE tbl1.col = 100 AND tbl12.col = 200
Or, more dynamically:
SELECT * FROM tbl1, tbl2 WHERE tbl1.col + 100 = tbl12.col;
-- with JOIN
SELECT * FROM tbl1 JOIN tbl2 ON (tbl1.col + 100) = tbl12.col;
select
*
from
tbl1
inner join
tbl2
on tbl1.col = 100 and tbl2.col = 200
weird, but it will work
If I understand your problem correctly, you have two tables that logically relate to each other but the current keys in the tables don't (but you have business rules that put them together). I think you need to create a cross-reference table that maps that relationship. The cross-reference table would map the primary keys of each other tables together to show the logical relationship between the data.
I think all of the others posters have made the assumption that the relationship is one you can calculate, but I don't think that is what you are asking. Correct me if I'm wrong.