Print output of count to DBMS - sql

I'm trying to run the same query over and over again so I can get the status of a process.
How do I use PL/SQL and the DBMS window or just the Query Result window to accomplish this?
My query looks like this:
Select count(table1.*) from table1
inner join table2 on table1.fk = table2.fk
inner join table3 on table3.fk = table2.fk
where
table1.col2={a value}
I've looked at several answers which discussed using a loop or dbms.output.put_line() but can't get my court to be what's displayed.
Sample data of info in these tables:
table1.columnName has company IDs and a program/process IDs
Col1 | Col2 | col3
1 | 42 | 2
2 | 42 | 2
3 | 42 | 2
1 | 41 | 2
4 | 41 | 2
1 | 43 | 2
Example output for the query where table1.col2=42 would be 3 because there are 3 rows where Col2 has value 42
Thank you

in the result window just type / and hit enter and you get the new count without typing in the entire query again.
in the pl_sql you can use a unix script and a sendmail command to get the results delivered to your inbox.

Related

Display two linked values for two id field pointing the same table

In my PostgreSQL database I have a table like this one:
id|link1|link2|
---------------
1 | 34 | 66
2 | 23 | 8
3 | 11 | 99
link1 and link2 fields are both pointing to the same table table2 which has id and descr fields.
I would make an SQL query that returns the same row the id and the descr value for the two field like this:
id|link1|link2|desc_l1|desc_l2|
-------------------------------
1 | 34 |66 | bla | sisusj|
2 | 23 | 8 | ghhj | yui |
3 | 11 | 99 | erd | bnbn |
I've try different queries, but everyone returns two rows per id instead of one.
How can I achieve these results in my PostgreSQL 9.04 database?
Normally, this query should work for you. Assume your first table name's table_name.
SELECT t.id, t.link1, t.link2,
l1.descr AS desc_l1,
l2.descr AS desc_l2
FROM table_name t
LEFT JOIN table2 l1
ON t.link1 = l1.id
LEFT JOIN table2 l2
ON t.link2 = l2.id;
you can use case here Like:
select link1,link2,
case
when link1='34' and link2='66' then 'bla'
when link1='23' and link2='8' then 'ghs'
when link1='11' and link2='99' then 'erd'
end as desc_li,
case
when link1='34' and link2='66' then 'sjm'
when link1='23' and link2='8' then 'yur'
when link1='11' and link2='99' then 'bnn'
end as desc_l2
from table1

Counting points/coordinates that lie within a bounding box

I have 2 tables. The first table contains following columns: Start_latitude, start_longitude, end_latitude, end_longitude, sum. The sum column is empty and needs to be filled based on second table.
The second table contains 3 columns: point_latitude, point_longitude
Table 1
-------------------------
|45 | 50 | 46 | 51 | null|
----|---------------------
|45 | 54 | 46 | 57 | null|
--------------------------
Table2:
---------------
| 45.5 | 55.2 |
---------------
| 45.8 | 50.6 |
---------------
| 45.2 | 56 |
---------------
The null values in table1-row1 would be 1 while in row2 it would be 2. It is the count of number of points that lie within the bounding box.
I can do it in python by writing functions to read values between dataframes. How can this be done in Postgresql. This is a sample problem statement that I came up with for my situation.
Update
This version was tested on PostgreSql 9.3 using SQL Fiddle
UPDATE table1 a
SET sum = sub.point_count
FROM (SELECT a.start_lat, a.end_lat, a.start_lon, a.end_lon, COUNT(*) as point_count
FROM table1 a, table2 b
WHERE b.point_lat BETWEEN start_lat AND a.end_lat
AND b.point_lon BETWEEN a.start_lon AND a.end_lon
GROUP BY a.start_lat, a.end_lat, a.start_lon, a.end_lon) as sub
WHERE a.start_lat = sub.start_lat
AND a.end_lat = sub.end_lat
AND a.start_lon = sub.start_lon
AND a.end_lon = sub.end_lon;
Original answer
Here is my solution, it is tested on MySQL but there is nothing specific about this code so it should work on PostgreSql as well
UPDATE table1 a,
(SELECT a.start_lat, a.end_lat, a.start_lon, a.end_lon, COUNT(*) as count
FROM table1 a, table2 b
WHERE b.point_lat BETWEEN start_lat AND a.end_lat
AND b.point_lon BETWEEN a.start_lon AND a.end_lon
GROUP BY a.start_lat, a.end_lat, a.start_lon, a.end_lon) as sub
SET sum = count
WHERE a.start_lat = sub.start_lat
AND a.end_lat = sub.end_lat
AND a.start_lon = sub.start_lon
AND a.end_lon = sub.end_lon
Note that this query would be much shorter if table1 contained a PK Id column.

SQL Performance on joining 2 scripts ORACLE

I have 2 scripts which are quite complicated, one was written by me personally, another was done 10 years ago. The first script gets necessary id's and executes in around 30 sec, example:
| ID | some other info ...
+----+--------------------
| 1 | ...
| 2 | ...
| 3 | ...
| 4 | ...
The second script get's some more complicated data, which is calculated through many sub queries, and executes in around 30 sec, ex:
| ID | Computed Info
+----+--------------------
| 1 | 111
| 2 | 222
| 3 | 333
| 4 | 444
Now my script1 needs to include some partial results from script2, because the script2 is very complicated it is quite hard to break down the necessary parts, that is why I have tried to left join results of the script2 to the script1 using ID's
SELECT TABLE1.*, TABLE2.COMPUTED_INFO FROM SCRIPT1 TABLE1 LEFT JOIN SCRIPT2 TABLE2 ON TABLE2.ID = TABLE1.ID
The result I got and also the expected result is:
| ID | some other info ... | Computed Info
+----+---------------------+---------------
| 1 | ... | 111
| 2 | ... | 222
| 3 | ... | 333
| 4 | ... | 444
The problem is that after joining both of them the time of execution is now 20+ min.
I have also tried
with table1 as
(script1),
table2 as
(script2)
select t1.*, t2.computed_data
from table1 t1 left join table2 t2 on t2.id = t1.id
Which resulted in 10+ min.
I am wondering why such thing occurs, when definitely script1 and script2 separately run in around 30 sec each, but when run together go as much as 10+
Is there another way to accomplish that?
You can create temp tables before joın those tables.
first create table temp1 as select * from script1
and create table temp2 as select * from script2
then select your query
SELECT temp1.*, temp2.COMPUTED_INFO FROM temp1 TABLE1 LEFT JOIN temp2 TABLE2 ON temp2.ID = temp1.ID
Last time when I had this kind of issue, I resolved it with a temporary table. I'd created temporary tables with the SCRIPT1 and SCRIPT2 results. Then added indices to the ID columns.
After this, a similar query than yours must execute faster.
This happened on a postgresql server, but the problem's root is the same. Usually an RDBMS can't optimise a subquery/resultset from a PROCEDURE/FUNCTION and cannot use indices on its rows.

Finding the difference between two sets of data from the same table

My data looks like:
run | line | checksum | group
-----------------------------
1 | 3 | 123 | 1
1 | 7 | 123 | 1
1 | 4 | 123 | 2
1 | 5 | 124 | 2
2 | 3 | 123 | 1
2 | 7 | 123 | 1
2 | 4 | 124 | 2
2 | 4 | 124 | 2
and I need a query that returns me the new entries in run 2
run | line | checksum | group
-----------------------------
2 | 4 | 124 | 2
2 | 4 | 124 | 2
I tried several things, but I never got to a satisfying answer.
In this case I'm using H2, but of course I'm interested in a general explanation that would help me to wrap my head around the concept.
EDIT:
OK, it's my first post here so please forgive if I didn't state the question precisely enough.
Basically given two run values (r1, r2, with r2 > r1) I want to determine which rows having row = r2 have a different line, checksum or group from any row where row = r1.
select * from yourtable
where run = 2 and checksum = (select max(checksum)
from yourtable)
Assuming your last run will have the higher run value than others, below SQL will help
select * from table1 t1
where t1.run in
(select max(t2.run) table1 t2)
Update:
Above SQL may not give you the right rows because your requirement is not so clear. But the overall idea is to fetch the rows based on the latest run parameters.
SELECT line, checksum, group
FROM TableX
WHERE run = 2
EXCEPT
SELECT line, checksum, group
FROM TableX
WHERE run = 1
or (with slightly different result):
SELECT *
FROM TableX x
WHERE run = 2
AND NOT EXISTS
( SELECT *
FROM TableX x2
WHERE run = 1
AND x2.line = x.line
AND x2.checksum = x.checksum
AND x2.group = x.group
)
A slightly different approach:
select min(run) run, line, checksum, group
from mytable
where run in (1,2)
group by line, checksum, group
having count(*)=1 and min(run)=2
Incidentally, I assume that the "group" column in your table isn't actually called group - this is a reserved word in SQL and would need to be enclosed in double quotes (or backticks or square brackets, depending on which RDBMS you are using).

How to sort sql result using a pre defined series of rows

i have a table like this one:
--------------------------------
id | name
--------------------------------
1 | aa
2 | aa
3 | aa
4 | aa
5 | bb
6 | bb
... one million more ...
and i like to obtain an arbitrary number of rows in a pre defined sequence and the other rows ordered by their name. e.g. in another table i have a short sequence with 3 id's:
sequ_no | id | pos
-----------------------
1 | 3 | 0
1 | 1 | 1
1 | 2 | 2
2 | 65535 | 0
2 | 45 | 1
... one million more ...
sequence 1 defines the following series of id's: [ 3, 1, 2]. how to obtain the three rows of the first table in this order and the rest of the rows ordered by their name asc?
how in PostgreSQL and how in mySQL? how would a solution look like in hql (hibernate query language)?
an idea i have is to first query and sort the rows which are defined in the sequence and than concat the other rows which are not in the sequence. but this involves tow queries, can it be done with one?
Update: The final result for the sample sequence [ 3, 1, 2](as defined above) should look like this:
id | name
----------------------------------
3 | aa
1 | aa
2 | aa
4 | aa
5 | bb
6 | bb
... one million more ...
i need this query to create a pagination through a product table where part of the squence of products is a defined sequence and the rest of the products will be ordered by a clause i dont know yet.
I'm not sure I understand the exact requirement, but won't this work:
SELECT ids.id, ids.name
FROM ids_table ids LEFT OUTER JOIN sequences_table seq
WHERE ids.id = seq.id
ORDER BY seq.sequ_no, seq.pos, ids.name, ids.id
One way: assign a position (e.g. 0) to each id that doesn't have a position yet, UNION the result with the second table, join the result with the first table, and ORDER BY seq_no, pos, name.