Compare two tables with different column numbers in sql - sql

I am using Sybase for my SQL coding.
I was comparing tables which have the same columns such as follows:
SELECT name, date, time, location
FROM
(SELECT * FROM table1
UNION ALL
SELECT * FROM table2) data
GROUP BY name, date, time, location
HAVING count(*)!=2
Now, I want to be able to compare the table1 and table2 but now table2 has another column called origin and I am not sure on how to extend my current logic to make it happen.
---Intention: to be able to compare the two tables with varying column numbers
---How to modify this code to do it?
I want to be able to show the differences between the two tables after the query.
May someone guide me? I dont want to use joins or minus, I prefer to use the UNION way.

If you want to union two different tables, you must make up missing columns. E.g.:
SELECT name, date, time, location, origin FROM table2
UNION ALL
SELECT name, date, time, location, null as origin FROM table1

I think the problem is that you actually want to ignore the extra column. The problem with using select * is that things can change.
SELECT name, date, time, location
FROM (
SELECT name, date, time, location FROM table1
UNION ALL
SELECT name, date, time, location FROM table2
) data
GROUP BY name, date, time, location
HAVING count(*) != 2
If you're not going to use select * in one half of the union there isn't any reason include origin in the first place.

Related

Select columns from second subquery if first returns NULL

I have two queries that I'm running separately from a PHP script. The first is checking if an identifier (group) has a timestamp in a table.
SELECT
group, MAX(timestamp) AS timestamp, value
FROM table_schema.sample_table
GROUP BY group, value
If there is no timestamp, then it runs this second query that retrieves the minimum timestamp from a separate table:
SELECT
group, MIN(timestamp) as timestamp, value AS value
FROM table_schema.src_table
GROUP BY group, value
And goes on from there.
What I would like to do, for the sake of conciseness, is to have a single query that runs the first statement, but that defaults to the second if NULL. I've tried with coalesce() and CASE statements, but they require subqueries to return single columns (which I hadn't run into being an issue yet). I then decided I should try a JOIN on the table with the aggregate timestamp to get the whole row, but then quickly realized I can't variate the table being joined (not to my knowledge). I opted to try joining both results and getting the max, something like this:
Edit: I am so tired, this should be a UNION, not a JOIN
sorry for any possible confusion :(
SELECT smpl.group, smpl.value, MAX(smpl.timestamp) AS timestamp
FROM table_schema.sample_table as smpl
INNER JOIN
(SELECT src.group, src.value, MIN(src.timestamp) AS timestamp
FROM source_table src
GROUP BY src.group, src.value) AS history
ON
smpl.group = history.group
GROUP BY smpl.group, smpl.value
I don't have a SELECT MAX() on this because it's really slow as is, most likely because my SQL is a bit rusty.
If anyone knows a better approach, I'd appreciate it!
Please try this:
select mx.group,(case when mx.timestamp is null then mn.timestamp else mx.timestamp end)timestamp,
(case when mx.timestamp is null then mn.value else mx.value end)value
(
SELECT
group, MAX(timestamp) AS timestamp, value
FROM table_schema.sample_table
GROUP BY group, value
)mx
left join
(
SELECT
group, MIN(timestamp) as timestamp, value AS value
FROM table_schema.src_table
GROUP BY group, value
)mn
on mx.group = mn.group

postgres: Querying across rows in multiple tables?

Is there a way to apply a single query across the concatenated rows of multiple tables? I have several tables storing metrics data, where data is initially collected in 10 second intervals, but is periodically rolled up into 1 minute intervals in another table and ultimately into 10 minute intervals in a third table.
That is, I want to be able to do something like:
SELECT value FROM table1 + table2 + table3
WHERE age(current_timestamp, time) > '2 days'
AND metrics_name = 'foo';
I don't think a JOIN operation is the right solution here. It looks like I can get the result I want using the UNION operator, which would look something like:
SELECT value from TABLE1 ...
UNION SELECT value FROM table2 ...
UNION SELECT value from TABLE3 ...
Where ... is the contents of my WHERE clause (etc), but this gets messy very quickly if the individual SELECT queries are complicated (and fails the "don't repeat yourself" mantra). Is there a different way of cracking this particular nut?
Use a nested query with the UNION in the nested quer. And I highly recommend you use UNION ALL unless you want to eliminate duplicates, which you won't in this case, so use UNION ALL.
SELECT
value
FROM (
SELECT value, age, metrics_name FROM Table1
UNION ALL SELECT value age, metrics_name FROM Table2
UNION ALL SELECT value age, metrics_name FROM Table3
) AS All_Metrics
WHERE
All_Metrics.age(current_timestamp, time) > '2 days'
AND All_Metrics.metrics_name = 'foo';

Merge 2 Tables from different Databases

Hypothetically I want to merge 2 tables from different databases into one table, which includes all the data from the 2 tables:
The result would look like something like this:
Aren't the entries in the result table redundant, because there are 2 entries with Porsche and VW? Or can I just add the values in the column 'stock' because the column 'Mark' is explicit?
you need to create database link to another database here is the example on how to create database link http://psoug.org/definition/create_database_link.htm
after creating your select statement from another database should look: select * from tableA#"database_link_name"
Then you need to use MERGE statement to push data from another database so the merge statement should look something like this.
you can read about merge statement here: https://docs.oracle.com/cd/B28359_01/server.111/b28286/statements_9016.htm#SQLRF01606
merge into result_table res
using (select mark, stock, some_unique_id
from result_table res2
union all
select mark, stock, some_unique_id
from tableA#"database_link_name") diff
on (res.some_unique_id = diff.some_unique_id )
when matched then
update set res.mark = diff.mark,
res.stock = diff.stock
when not matched then
insert
(res.mark,
res.stock,
res.some_unique_id)
values
(diff.mark,
diff.stock,
diff.some_unique_id);
I hope this will help you
SELECT ROW_NUMBER() OVER (ORDER BY Mark) AS new_ID, Mark, SUM(Stock) AS Stock
FROM
(
SELECT Mark,Stock FROM Database1.dbo.table1
UNION ALL
SELECT Mark,Stock FROM Database2.dbo.table2
) RESULT
GROUP BY Mark
Try this:
Select Mark, Stock, row_number() over(order by Mark desc) from table1
union all
Select Mark, Stock, row_number() over(order by Mark desc) from table2
regardless of the data redundancy, you could use union all clause to achieve this. Like:
Select * From tableA
UNION ALL
Select * From tanleB
Make sure the total number of columns and datatype should be matched between each
Don't forget to use fully qualified table names as the tables are in different databases
SELECT
Mark
,Stock
FROM Database1.dbo.table1
UNION ALL
SELECT
Mark
,Stock
FROM Database2.dbo.table2
If these are 2 live databases and you would need to constantly include rows from the 2 databases into your new database consider writing the table in your 3rd database as a view rather.
This way you can also add a column specifying which system the datarow is coming from. Summing the values is an option, however if you ever have a query regarding a incorrect summed value how would you know which system is the culprit?

Join two SQL Server tables [duplicate]

This question already has answers here:
Combine two tables for one output
(2 answers)
Closed 8 years ago.
I have two tables now I need a select or join command in SQL to have the third table just like image below
My two tables are like this:
I only know a simple things about join command in SQL, should I use join or something else?
I do not want have the third table in my database, I want that for a short time (something like virtual table). Please help !
You are actually looking for UNION or UNION ALL.
First of all, there is no condition on which to JOIN tables (review your documentation on JOIN) and JOIN is used for retrieving information about one logical element, let's say Event in your case, which has details stored in more tables.
Secondly, JOIN will make one result set with all of the columns of your two tables, when actually you are not trying to get all columns, but all rows.
For this you will have to use UNION or UNION ALL like this:
SELECT
EventID,
ID,
EventName,
Date,
Pic,
Privacy
FROM Table1
UNION ALL
SELECT
PLID AS EventID,
ID AS ID,
PlaceName AS EventName,
Date AS Date,
NULL AS Pic,
NULL AS Privacy
FROM Table2
In order to sort the result you get from the result set returned by the queries above you will need to wrap your above SELECT statements with another SELECT and use a WHERE clause at that level, like below:
SELECT *
FROM (SELECT
EventID,
ID,
EventName,
Date,
Pic,
Privacy
FROM Table1
UNION ALL
SELECT
PLID AS EventID,
ID AS ID,
PlaceName AS EventName,
Date AS Date,
NULL AS Pic,
NULL AS Privacy
FROM Table2) AS Result
WHERE Date > '2014-05-26'
What you're looking to do is a UNION or UNION ALL, not a join. See: http://www.w3schools.com/sql/sql_union.asp
UNION combines two tables without connecting their content. Your example shows all 4 records from the original tables unmodified.
A JOIN solution links the two tables. It's very common and you will probably use it if you're building a relational database, but it won't give you the example result.
Since the two tables don't have identical # of columns, you have to help it out here:
SELECT EventID, EventName, Date, Pic, privacy FROM [table 1]
UNION ALL
SELECT PLID, PlaceName, Date, null, null FROM [table 2]
You want to have one table from two different tables. So you need unified result set from each by renaming column in SELECT statement:
SELECT `EventID` AS `ObjectID`, `EventName` AS `ObjectName`, .... FROM table_1 ...
similary with table_2
Then combine to one result set:
SELECT `ID` AS `ObjectID`, `EventName` AS `ObjectName`, .... FROM table_1 ...
UNION
SELECT `PlaceID` AS `ObjectID`, `PlaceName` AS `ObjectName`, .... FROM table_2 ...
My mistake, I didn't take the time to examine the pictures fully. you would have to use Union since you want to return what is in both tables.

SQL query to select one of multiple rows from a table

I have a table which contains more than one row for a particular value . Here is the table structure:
NAME,NUMBER,STATUS,DESC,START_DATE,END_DATE
A,3,X,DetailsOfX,13-10-15,13-10-15
A,2,Y,DetailsOfY,13-10-15,13-10-15
A,2,Z,DetailsOfZ,13-10-15,13-10-15
A,1,X,DetailsOfX,12-10-15,12-10-15
The output i need is i.e.
A,3,X,DetailsOfX,13-10-15,13-10-15
A,2,Y,DetailsOfY-DetailsofZ,13-10-15,13-10-15
A,1,X,DetailsOfX,12-10-15,12-10-15
So basically i want to select one of two or more rows from a table with data from columns from both the rows (in bold above). The query below i tried using JOIN returns 4 rows.
SELECT A.NAME,A.NUMBER,B.STATUS,A.DESC||"-"||B.DESC,A.START_DATE,A.END_DATE
FROM TABLE A
JOIN (SELECT NUMBER,STATUS,DESC,START_DATE,END_DATE FROM TABLE WHERE NAME='A') B
ON A.NAME=B.NAME AND
A.NUMBER=B.NUMBER
Can somebody help me with the query that would work.
Thanks
If you are using IBM i 7.1 (formerly known as OS/400), you should be able do this with two tricks: hierarchical queries, and XML functions.
See my tutorial under Q: SQL concatenate strings which explains how to do this on DB2 for i in order to merge the descriptions.
GROUP BY any fields by which you would want rows combined into one, but all other columns must be the result of an aggregate function. So for example, if you want one row per name, number, but have various values for Status, StartDate, EndDate, then you will need to say something like min(Status), min(StartDate), max(EndDate). Is the minimum status code actually the one you want to report?
If your OS is at version 6.1, you may still be able to use a conventional recursive query (or under v5r4), but you might need an addtional CTE (or two?) to concatenate the descriptions.
You need to use GROUP BY and FOR XML PATH:
SELECT
X.NAME, X.NUMBER, X.STATUS,
STUFF((
SELECT '-' + [Desc] AS Desc
FROM YourTable Y
WHERE Y.ID = X.ID
FOR XML PATH(''),TYPE),1,1,'') AS DescValues,
StartDate,
EndDate
FROM YourTable X
GROUP BY Name, Number, Status, StartDate, EndDate
This is assuming you want separate rows for any differences in name, number, status, start date, or end date.
Also, this is assuming SQL Server.