I'm trying to insert the MINUS values from two tables (sample data) on ORACLE. I can insert all rows but I can't get it to work with the rows that are missing in the other table:
Sample Data:
SALES TABLE SALES2 TABLE S_DETAILS TABLE
=================== =================== ==================
ID_SALE|DATE_SALE ID_SALE|DATE_SALE ID_SALE|SALE_DETAILS
100 |12/12/2010 100 |12/12/2010 100 |SHIPPED
101 |5/10/2011 101 |5/10/2011 101 |WAITING
102 |10/9/2012 102 |SHIPPED
103 |5/10/2011 103 |PROCESSING
My Code:
INSERT INTO SALES_RESUME(ID_SALE,DATE_SALE,TOTAL_SALE,SALE_DETAILS)
SELECT A.ID_SALE,A.DATE_SALE,B.TOTAL_SALE,B.SALE_DETAILS
FROM SALES A
JOIN S_DETAILS B ON A.ID_SALE = B.ID_SALE
WHERE A.ID_SALE IN (SELECT ID_SALE FROM SALES
MINUS
SELECT ID_SALE FROM SALES2);
I want to insert rows into SALES_RESUME when the ID_SALE is in the resulting MINUS subquery, inserting:
SALES_RESUME
==============================
ID_SALE|DATE_SALE|SALE_DETAILS
102 |10/9/2012|SHIPPED
103 |5/10/2011|PROCESSING
Thanks in advance
Your query would appear to do what you want. But why not just write this?
WHERE A.ID_SALE NOT IN (SELECT ID_SALE FROM SALES2 WHERE ID_SALE IS NOT NULL); -- assuming SALES2.ID_SALE is never NULL
You already know that ID_SALE is in the first table.
If I got it, I think this query will work
SELECT A.ID_SALE,A.DATE_SALE,B.TOTAL_SALE,B.SALE_DETAILS
FROM ((select id_sale,DATE_SALE from SALES) minus (select id_sale,DATE_SALE from SALES2)) A
JOIN S_DETAILS B on A.id = B.id
Related
I am trying to execute a query in sql to get only the records of agents associated with multiple descriptions
Example:
Table name: AGENT
AGENCY_ID PRODUCT_DESC AGENT number
100 ABC 2000
101 ABC 2001
101 XYZ 2002
102 XYZ 2003
AGENCY_ID 101 has both ABC and XYZ descriptions.From the table, I want to pull only records from the overlapping agency
In the above case I want to pull only:
AGENCY_ID PRODUCT_DESC AGENT number
101 ABC 2001
101 XYZ 2002
I am also trying to execute this in the Business objects webi report query filters.
Please advise me in getting to the solution of my issue.
Thanks in advance!
In SQL you can use subquery
select t.*
from table t
where exists (select 1 from table where AGENCY_ID = t.AGENCY_ID and PRODUCT_DESC <> t.PRODUCT_DESC);
Most of DBMS doesn't work with <> so use != instead in case.
One of the way
DECLARE #tblActivity AS TABLE (AGENCY_ID INT , PRODUCT_DESC VARCHAR(100), AGENTnumber INT)
INSERT INTO #tblActivity (Agency_id,Product_Desc,AGentNumber)
VALUES
(100,'ABC', 2000),
(101,'ABC', 2001),
(101,'XYZ', 2002),
(102,'XYZ', 2003)
SELECT tmp.*
FROM #tblActivity tmp
INNER JOIN #tblActivity tmp1 ON tmp1.AGENCY_ID = tmp.AGENCY_ID
AND tmp1.AGENTnumber != tmp.AGENTnumber
AND tmp1.PRODUCT_DESC != tmp.PRODUCT_DESC
Alternatively if your RDBMS supports window/analytic functions; one could get the count of duplicate agent_IDs and then use that count as a filter.
Example: The cte here is just to setup data in a Hana database so I use from dummy to get a derived table called CTE.
Then we use that derived table in a subquery with the count() analytic to get a count of records by agency_ID and then we show all such records Where the count is > 1
A subquery/inline view is need as we need the CNT result to be generated before we can limit by it; and one can't use a analytic/window function in a having / where clause.
With CTE (AGENCY_ID,PRODUCT_DESC,AGENT_number) AS (
SELECT 100, 'ABC', 2000 from dummy union all
SELECT 101, 'ABC', 2001 from dummy union all
SELECT 101, 'XYZ', 2002 from dummy union all
SELECT 102, 'XYZ', 2003 from dummy)
SELECT B.*
FROM (SELECT *, count(*) over (partition by Agency_ID) cnt
FROM CTE) B
WHERE cnt > 1
I have the following master table called Master and sample data
ID---------------Date
1 2014-09-07
2 2014-09-07
3 2014-09-08
The following details table called Details
masterId-------------Name
1 John Walsh
1 John Jones
2 John Carney
1 Peter Lewis
3 John Wilson
Now I want to find out the count of Master records (grouped on the Date column) whose corresponding details record with Name having the value "John".
I cannot figure how to write a single SQL statement for this job.
**Please note that join is needed in order to find master records for count. However, such join creates duplicate master records for count. I need to remove such duplicate records from being counted when grouping on the Date column in the Master table.
The correct results should be:
count: grouped on Date column
2 2014-09-07
1 2014-09-08
**
Thanks and regards!
This answer assumes the following
The Name field is always FirstName LastName
You are looking once and only once for the John firstname. The search criteria would be different, pending what you need
SELECT Date, Count(*)
FROM tblmaster
INNER JOIN tbldetails ON tblmaster.ID=tbldetails.masterId
WHERE NAME LIKE 'John%'
GROUP BY Date, tbldetails.masterId
What we're doing here is using a wilcard character in our string search to say "Look for John where any characters of any length follows".
Also, here is a way to create table variables based on what we're working with
DECLARE #tblmaster as table(
ID int,
[date] datetime
)
DECLARE #tbldetails as table(
masterID int,
name varchar(50)
)
INSERT INTO #tblmaster (ID,[date])
VALUES
(1,'2014-09-07'),(2,'2014-09-07'),(3,'2014-09-08')
INSERT INTO #tbldetails(masterID, name) VALUES
(1,'John Walsh'),
(1,'John Jones'),
(2,'John Carney'),
(1,'Peter Lewis'),
(3,'John Wilson')
Based on all comments below, this SQL statement in it's clunky glory should do the trick.
SELECT date,count(t1.ID) FROM #tblmaster mainTable INNER JOIN
(
SELECT ID, COUNT(*) as countOfAll
FROM #tblmaster t1
INNER JOIN #tbldetails t2 ON t1.ID=t2.masterId
WHERE NAME LIKE 'John%'
GROUP BY id)
as t1 on t1.ID = mainTable.id
GROUP BY mainTable.date
Is this what you want?
select date, count(distinct m.id)
from master m join
details d
on d.masterid = m.id
where name like '%John%'
group by date;
This is my current table:
Sales Table
OrderID Customer_ID Customer_Name
1 12 Bob
2 18 Ben
3 11 Harry
OrderID is the primary key
I have a temporary table Temp1:
Order_CreateDate Order_ReturnDate
20051102 20051104
20051103 20051108
20051104 20051105
I want to change the dates YYYYMMDD in Temp1 table, to YYYY-MM-DD, and move it to table, this code below does not work if I insert straight into Sales Table as it displays error saying:
Cannot insert the value NULL into column 'Order_ID', table 'car_rental.dbo.DataInCentralDatabase2'; column does not allow nulls. INSERT fails
However if I test it out by outputting to another temporary table, temp2, it works.
INSERT INTO [dbo].[sales]([Order_CreateDate])
SELECT
CONVERT(date,Order_CreateDate,111) AS Order_CreateDate
FROM dbo.temp1
But running this code two times for temp2 table (for the two converted columns) has the following result:
Order_CreateDate Order_ReturnDate
2005-11-02
2005-11-03
2005-11-04
NULL 2005-11-04
NULL 2005-11-08
NULL 2005-11-05
I know this question is extremely confusing, but as the end result I want it to become like this:
OrderID Customer_ID Customer_Name Order_CreateDate Order_ReturnDate
1 12 Bob 2005-11-02 2005-11-04
2 18 Ben 2005-11-03 2005-11-08
3 11 Harry 2005-11-04 2005-11-05
Any ideas on how to tackle this?
You need another column in Temp1 table as
OrderID Order_CreateDate Order_ReturnDate
1 20051102 20051104
2 20051103 20051108
3 20051104 20051105
Use Update query and not Insert query
UPDATE a set
Order_CreateDate=CONVERT(datetime,b.Order_CreateDate,111),
Order_ReturnDate=CONVERT(datetime,b.Order_ReturnDate,111)
from [dbo].[sales] a join [dbo].[Temp1] b on a.OrderID = b.OrderID
At the first, you should get an updated version of temp1 like this:
select
CONVERT(date,Order_CreateDate,111) as Order_CreateDate,
CONVERT(date,Order_ReturnDate,111) as Order_ReturnDate,
OrderID
into #temp2
from temp1
then, update your main table with join on temp1, like this:
update s
s.Order_CreateDate = t.Order_CreateDate,
s.Order_ReturnDate = t.Order_ReturnDate
from sales s
inner join #temp2 t
on s.OrderID = t.OrderID
I have a table:
accdate (DATETIME) | value (INT)
-------------------+------------
|
The accdate-column contains datasets on hour-granularity. That means, there are datetimes in the format YYYY-mm-dd HH:00:00. If I view the table using SELECT * FROM mytable ORDER BY accdate ASC I get an ordered table by accdate. But mytable does not contain all possible dates and hours between the first row and the last (some dates are missing in the times my program is not running). I want to have default-values for all possible date+hour-combinations between the first and the last row.
I know this can be solved by using a LEFT JOIN with another table, that contains all possible dates in this range. But how do I construct such a table in a SQL-Statement? I think it is not senseful to populate the table with dummy data, if I can resolve the problem in the query.
Example:
accdate (DATETIME) | value (INT)
---------------------+------------
2011-11-11 19:00:00 | 50
2011-11-11 20:00:00 | 53
2011-11-11 22:00:00 | 16
2011-11-12 06:00:00 | 15
2011-11-12 07:00:00 | 150
The date 2011-11-11 21:00:00 and the range between 23 pm and 5am is missing. For these dates there should be a row in the result-table (containing a 0 in the value-column).
I hope you understand my problem. If something is unclear, please comment. Thank you.
With SQLite 3.8.3 or later, you can use a common table expression to generate values out of nothing:
WITH RECURSIVE AllDates(accdate)
AS (VALUES('2011-11-11 00:00:00')
UNION ALL
SELECT datetime(accdate, '+1 hour')
FROM AllDates
WHERE accdate < '2011-11-12 10:00:00')
SELECT AllHours.accdate,
MyTable.value
FROM AllHours
LEFT JOIN MyTable USING (accdate)
The only way I can think of is to use a left join with the same table, adding to the desired field on the join and union the result with the actual results to complete the set:
Example setup:
CREATE TABLE tmp (
id INT IDENTITY,
number INT
);
-- insert some incomplete sequenced values
INSERT INTO tmp (number) VALUES(1);
INSERT INTO tmp (number) VALUES(3);
INSERT INTO tmp (number) VALUES(4);
Example query:
-- select your actual data
SELECT number
FROM tmp
UNION
-- select the missing data
SELECT a.number + 1
FROM tmp a
LEFT JOIN tmp b ON a.number + 1 = b.number
WHERE b.id IS NULL
-- order the complete set
ORDER BY number ASC;
This will not work if you have more than one missing value between your results (eg.: 1 and 4), but if your data misses only single hours between each result this Works like a charm.
I have a table in which there can be two newspaper publishing dates for a particular value which is inserted in a single column only under NewsPaperDate. All the remaining values get duplicated. Now I have to write a query in which the two NewsPaperDate values should be shown in a single row under two columns, NewsPaperDate1 and NewsPaperDate2, with the remaining values. Can anyone help in this? The DataBase is Sql Server
The Table structure is
You need to join the table to itself. There are different ways of doing this but based on your screenshot you could do:
select
a.yonja_no,
a.newspaper_date as newspaperdate1,
b.newspaper_date as newspaperdate2
from newspapertable a, newspapertable b
where a.yonja_no = b.yonja_no
and a.newspapere_s > b.newspapere_s
;
(Edited: see comments)
check fiddle link for query execution with sample data
create table tab1(newspaperDate number,b number,c number);
INSERT INTO tab1 VALUES(1,2,3);
INSERT INTO tab1 VALUES(2,2,3);
INSERT INTO tab1 VALUES(3,3,4);
SELECT t1.newspaperDate AS date1,t2.newspaperDate AS date2 , t1.b AS b1,t1.c AS c1 FROM tab1 t1 , tab1 t2
WHERE t1.newspaperDate < t2.newspaperDate AND t1.b=t2.b ;
OUTPUT
| DATE1 | DATE2 | B1 | C1 |
---------------------------
| 1 | 2 | 2 | 3 |
Joining a table to itself is the best approach for your query. Read
this
http://www.thunderstone.com/site/texisman/joining_a_table_to_itself.html