How to draw interconnected tables with PlantUML - datatables

I try to draw interconnected tables (not Eentities!) with PlantUml. Unfortunately, I could not find any possibility to name a table. The only solution I could use is to define it in another component, eg. an object, to be able to make interconnections between them.
#startuml
object Organization {
<#lightblue,#black>|= organizationNo |= name |= address |
<#white>| OS07 | Sphereways | 22 Rabbit Rd, London |
<#white>| OO7 | Orco | 16 Adam St, Nuremberg |
<#white>| OC11 | Cruxolutions | 163 Olga St, Budapest |
}
object OrgCust {
<#lightblue,#black>|= organizationNo |= customerNo |
<#white>| OS07 | CM67 |
<#white>| OS7 | CM67 |
<#white>| OC11 | CH11 |
}
object Customer {
<#lightblue,#black>|= customerNo |= fName |= lName |= creditLimit |
<#white>| CJ13 | John | Jeschke | 5000 |
<#white>| CK37 | Nina | Knabel | 2000 |
<#white>| CM67 | Felix | Magee | 1300 |
<#white>| CH11 | Lilla | Hopka | 3000 |
}
Organization -[hidden]-> OrgCust
OrgCust -[hidden]-> Customer
Organization ||--o{ OrgCust
Customer ||--o{ OrgCust
#enduml
It looks not that bad, but the extra frames disturb me a bit. Would be possible to avoid these frames and connect the tables directly (but maybe still have a caption for the tables)?

You can try to draw them as notes (the Creole syntax doesn't work in Rectangle or Package elements unfortunately). You have to hide the note outline and background:
#startuml
<style>
note {
backgroundcolor white
shadowing 0
linecolor transparent
}
</style>
note as Organization
<#lightblue,#black>|= organizationNo |= name |= address |
<#white>| OS07 | Sphereways | 22 Rabbit Rd, London |
<#white>| OO7 | Orco | 16 Adam St, Nuremberg |
<#white>| OC11 | Cruxolutions | 163 Olga St, Budapest |
end note
note as OrgCust
<#lightblue,#black>|= organizationNo |= customerNo |
<#white>| OS07 | CM67 |
<#white>| OS7 | CM67 |
<#white>| OC11 | CH11 |
end note
note as Customer
<#lightblue,#black>|= customerNo |= fName |= lName |= creditLimit |
<#white>| CJ13 | John | Jeschke | 5000 |
<#white>| CK37 | Nina | Knabel | 2000 |
<#white>| CM67 | Felix | Magee | 1300 |
<#white>| CH11 | Lilla | Hopka | 3000 |
end note
Organization -[hidden]-> OrgCust
OrgCust -[hidden]-> Customer
Organization ||--o{ OrgCust
Customer ||--o{ OrgCust
#enduml
To get a caption for the tables, you could format it in the table somehow? Or add <b>Caption here</b> on a line inside the note (beginning or end)?
EDIT
I also discovered that you can embed the table in the name of a class, such as:
#startuml
<style>
class {
BackgroundColor transparent
linecolor transparent
}
</style>
hide empty members
hide circle
class "<#lightblue,#black>|= organizationNo |= name |= address |\n\
<#white>| OS07 | Sphereways | 22 Rabbit Rd, London |\n\
<#white>| OO7 | Orco | 16 Adam St, Nuremberg |\n\
<#white>| OC11 | Cruxolutions | 163 Olga St, Budapest |" as Organization {
}
#enduml

Related

Using Snowflake SQL how do you find two records and then change another one based on those records to a predefined record using a local variable?

Using SQL how do you use two records to find a place, hold onto that place and use that record to replace 'Nonsense' value with that held onto place? I am going to show what I have been able to write so far, but then write out what I am still trying to figure out:
SELECT * FROM "TABLES". "ACCTS_OF_SUPERHEROS".;
DECLARE #count_rows INT = 0;
DECLARE #row_total INT = 0;
DECLARE #refAcctNum INT = 0;
DECLARE #selectedPlaceName TINYTEXT;
SET #row_total = SELECT COUNT (*)
WHILE countRows < row_total
for each acct_num store value in refAcctNum.
Using refAcctNum find place: "Gotham City", "Central City", "Metropolis", "Smallville", "Star City", "Fawcett City" store that in selectedPlaceName.
If refAccountNumber has Nonsense then replace with selectedPlaceName record
otherwise add + 1 to countRows and repeat.
END
Current table data; "ACCTS_OF_SUPERHEROS" table:
| row | acct_num | exact_address | place
| --- | -------- |------------------|--------
| 1 | 049403 | 344 Clinton Str | Metropolis
| 2 | 049403 | 344 Clinton Str | Nonsense
| 3 | 049206 | 1007 Mountain Dr | Gotham City
| 4 | 049206 | 1007 Mountain Dr | Gotham City
| 5 | 049206 | 1096 Show Dr. | Fawcett City
| 6 | 049206 | 1096 Show Dr. | Nonsense
| 7 | 049206 | NULL | Nonsense
| 8 | 049291 | 1938 Sullivan Pl | Smallville
| 9 | 049293 | 700 Hamilton Str | Central City
| 10 | 049396 | 800 Nonsense Way | Nonsense
| 11 | 049396 | NULL | Nonsense
Desired output:
| row | acct_num | exact_address | place
| --- | -------- |------------------|--------
| 1 | 049403 | 344 Clinton Str | Metropolis
| 2 | 049403 | 344 Clinton Str | Metropolis
| 3 | 049206 | 1007 Mountain Dr | Gotham City
| 4 | 049206 | 1007 Mountain Dr | Gotham City
| 5 | 049206 | 1096 Show Dr. | Fawcett City
| 6 | 049206 | 1096 Show Dr. | Fawcett City
| 7 | 049206 | NULL | Fawcett City
| 8 | 049291 | 1938 Sullivan Pl | Smallville
| 9 | 049293 | 700 Hamilton Str | Central City
| 10 | 049396 | 800 Tidal Way | Star City
| 11 | 049396 | NULL | Star City
You can use window functions:
select t.*,
max(case when place <> 'Nonsense' then place end) over (partition by acct_num) as imputed_place
from t;
This returns NULL if all the rows are 'Nonsense' for a given acct_num. You can use COALESCE() to replace the value with something else.
I was reading through the available list of window functions in Snowflake and think you're going to need a new window function for this. Perhaps someone can find a more built-in way, but anyway here's a user defined table function REPLACE_WITH_LKG implemented as a window function that will replace a bad value with the last known good value. As long as I was going to write it, I thought it may as well be general purpose, so it matches "bad" values using a regular expression and JavaScript RegExp options.
create or replace function REPLACE_WITH_LKG("VALUE" string, "REGEXP" string, "REGEXP_OPTIONS" string)
returns table(LKG_VALUE string)
language javascript
strict immutable
as
$$
{
initialize: function (argumentInfo, context) {
this.lkg = "";
},
processRow: function (row, rowWriter, context) {
const rx = new RegExp(row.REGEXP, row.REGEXP_OPTIONS);
if (!rx.test(row.VALUE)) {
this.lkg = row.VALUE;
}
rowWriter.writeRow({LKG_VALUE: this.lkg});
},
finalize: function (rowWriter, context) {},
}
$$;
select S.*, LKG.LKG_VALUE as PLACE
from superhero S, table(REPLACE_WITH_LKG(PLACE, 'Nonsense', 'ig')
over(partition by null order by "ROW")) LKG;
;
A note on performance; the way the data shows this the're no partition other than the entire table. That's because the one obvious place to partition, by account, won't work. Row 10 is getting its value from what would be a different window if using account, so the way the sample data appears it needs to be a window that spans the entire table. This will not parallelize well and should be avoided for very large tables.

Include null values and joins properly in query

I am using oracle sqldeveloper and I'm trying to generate results that include customer information under certain criteria that is searched by date range. I feel like I am close however I would like to include accounts that apply all the criteria but haven't made payments as well.
My intended result is to look something like this:
CYCLENUMB | WOCREATIONDATE | POSTINGDATE | CUSTOMERNUMBER | FIRSTNAME | LASTNAME | ADDRESS | WOORDERTYPE | DESCRIPTION | PAYMENT
12 | 29-JUL-20 | 01-AUG-20 | 345506 | Luke | Skywalker| 123 Lakeway Dr. | 636 |Completed | $100
24 | 01-AUG-20 | 07-AUG-20 | 456923 | Leia | Skywalker| 456 Lakeway Dr. | 636 |Completed | $300
35 | 17-AUG-20 | 24-AUG-20 | 596854 | Chewy | Wookie | 789 Lakeway Dr. | 636 |Completed | NULL
80 | 21-AUG-20 | 28-AUG-20 | 695067 | Han | Solo | 432 Wrongturn Dr.| 636 |Completed | NULL
66 | 25-AUG-20 | 30-AUG-20 | 235645 | Count | Dooku | 534 Wrongturn Dr.| 636 |Completed | $225
However my results are coming out just like this
CYCLENUMB | WOCREATIONDATE | POSTINGDATE | CUSTOMERNUMBER | FIRSTNAME | LASTNAME | ADDRESS | WOORDERTYPE | DESCRIPTION | PAYMENT
12 | 29-JUL-20 | 01-AUG-20 | 345506 | Luke | Skywalker| 123 Lakeway Dr. | 636 |Completed | $100
24 | 01-AUG-20 | 07-AUG-20 | 456923 | Leia | Skywalker| 456 Lakeway Dr. | 636 |Completed | $300
66 | 25-AUG-20 | 30-AUG-20 | 235645 | Count | Dooku | 534 Wrongturn Dr.| 636 |Completed | $225
Below is the query I'm trying to run
select customermaster.cyclenumber as CYCLENUMB,
workorder.creationdate as WOCREATIONDATE,
MAX(cushistory.postingdate) as POSTINGDATE,
cushistory.customernumber as CUSTOMERNUMBER,
customerpersonalinfo.firstname as FIRSTNAME,
customerpersonalinfo.lastname as LASTNAME,
premiseaddress.Concatenated_Address as ADDRESS,
workorder.ordertype as WOORDERTYPE,
workorderstatus.description as DESCRIPTION,
SUM(cushistory.moneysegment1) as PAYMENT
from customermaster, workorder, customerpersonalinfo,
(select
premiseaddress.company as COMPANY,
premiseaddress.premisenumber as PREMISENUMBER,
((to_char(premiseaddress.currpremisestreetnumber) || ' ') || premiseaddress.currpremisestreetname) as Concatenated_Address
from premiseaddress)
premiseaddress, workorderstatus, cushistory
where workorder.ordertype = 636
and cushistory.moneytypecode1 = 7
and workorder.application = 3
and cushistory.postingdate between '01-Aug-20' and '31-Aug-20'
and customermaster.customernumber = cushistory.customernumber
and cushistory.customernumber = workorder.customernumber
and customermaster.company = workorder.company
and customermaster.accounttype = workorder.application
and customermaster.customernumber = workorder.customernumber
and workorder.application = workorderstatus.application
and workorder.completecode = workorderstatus.workorderstatus
and customermaster.company = customerpersonalinfo.company
and customermaster.occupantcisnumber =customerpersonalinfo.cisnumber
and customermaster.company = premiseaddress.company
and customermaster.premisenumber = premiseaddress.premisenumber
GROUP BY customermaster.cyclenumber,
workorder.wocreationdate ,
cushistory.postingdate,
customermaster.customernumber,
customerpersonalinfo.firstname,
customerpersonalinfo.lastname,
premiseaddress.Concatenated_Address,
workorder.ordertype,
workorderstatus.description
ORDER BY workorder.creationdate asc
I included a subquery for simplifying customer address. Postingdate from cushistory is the date range filer I am applying.
Please note that custhistory table is the main table that holds customernumbers and payments. I wanted to left join it with workorder table to include null values but haven't figured out a surefire way to do it.

Hide org src dbpassword header to other place

I am learning through postgres with "Practical SQL"
#+begin_src sql :engine postgresql :dbuser org :dbpassword 1618 :database analysis
select * from teachers
order by hire_date desc
limit 3;
#+end_src
#+RESULTS:
| id | first_name | last_name | school | hire_date | salary |
|----+------------+-----------+---------------------+------------+--------|
| 1 | Janet | Smith | F.D. Roosevelt HS | 2011-10-30 | 36200 |
| 4 | Samantha | Bush | Myers Middle School | 2011-10-30 | 36200 |
| 6 | Kathleen | Roush | F.D. Roosevelt HS | 2010-10-22 | 38500 |
Reference to the header of :dbpassword,
Is it possible to save it other places like the header of files so as to avoid exposing it as header in src?
You should be able to use :dbpassword (read-passwd "Password: "). The (...) is just ordinary Emacs Lisp code, you're free to use others.

Retrieve closest road when given (lat, long) using OSM in Postgres with Postgis using SQL query

Given a set (lat, long) I am trying to find the maximum speed using "max_speed" and street type using "highway".
I have loaded my database (Postgres and Postgis) as follows:
$ osm2pgsql -c -d gis --slim -C 50000 /var/lib/postgresql/data/germany-latest.osm.pbf
The closest related question I could find was How to query all shops around a certain longitude/latitude using osm-postgis?. I have taken the query, and plugged in a (lat, long) that I found in google maps for the city center of Munich (as the post was also related to city center Munich and I have the map for Germany). The result turns up empty.
gis=# SELECT name, shop FROM planet_osm_point WHERE ST_DWithin(way ,ST_SetSrid(ST_Point(48.137969, 11.573829), 900913), 100);
name | shop
------+------
(0 rows)
Also when looking into the planet_osm_nodes, which contains (lat, long) pairs directly, I end up with no results:
gis=# SELECT * FROM planet_osm_nodes WHERE ((lat BETWEEN 470000000 AND 490000000) AND (lon BETWEEN 100000000 AND 120000000)) LIMIT 10;
id | lat | lon | tags
----+-----+-----+------
(0 rows)
I verified the data is in my database:
gis=# SELECT COUNT(*) FROM planet_osm_point;
count
---------
9924531
(1 row)
and
gis=# SELECT COUNT(*) FROM planet_osm_nodes;
count
-----------
288597897
(1 row)
So ideally, my question would be
Q: How can I find the "max speed" and "highway" given a set (lat, lon)
alternatively, my questions is:
Q: How do I get the query from the other stack overflow post to work?
My best guess is that I need to transform my (lat, lon) in some way, or that I simply have the wrong data for whatever reason.
Edit: added sample data as requested:
gis=# SELECT * FROM planet_osm_point LIMIT 1;
osm_id | access | addr:housename | addr:housenumber | addr:interpolation | admin_level | aerialway | aeroway | amenity | area | barrier | bicycle | brand | bridge | boundary | building | capital | construction | covered | culvert |
cutting | denomination | disused | ele | embankment | foot | generator:source | harbour | highway | historic | horse | intermittent | junction | landuse | layer | leisure | lock | man_made | military | motorcar | name | natural | off
ice | oneway | operator | place | poi | population | power | power_source | public_transport | railway | ref | religion | route | service | shop | sport | surface | toll | tourism | tower:type | tunnel | water | waterway | wetland | wi
dth | wood | z_order | way
-----------+--------+----------------+------------------+--------------------+-------------+-----------+---------+---------+------+---------+---------+-------+--------+----------+----------+---------+--------------+---------+---------+
---------+--------------+---------+-----+------------+------+------------------+---------+----------+----------+-------+--------------+----------+---------+-------+---------+------+----------+----------+----------+------+---------+----
----+--------+----------+-------+-----+------------+-------+--------------+------------------+---------+-----+----------+-------+---------+------+-------+---------+------+---------+------------+--------+-------+----------+---------+---
----+------+---------+----------------------------------------------------
304070863 | | | | | | | | | | | | | | | | | | | |
| | | | | | | | crossing | | | | | | | | | | | | | |
| | | | | | | | | | | | | | | | | | | | | | | |
| | | 010100002031BF0D0048E17A94F19F2941CDCCCCDCC60D5741
(1 row)
and
gis=# SELECT * FROM planet_osm_nodes LIMIT 1;
id | lat | lon | tags
--------+-----------+----------+------
234100 | 666501948 | 80442755 |
(1 row)
Edit 2: There was a mention regarding "SRID", so I added example data from another table:
gis=# SELECT * FROM spatial_ref_sys LIMIT 1;
srid | auth_name | auth_srid | srtext
| proj4text
------+-----------+-----------+------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------------
----------------------------------------------------------------------------------------------------------------------------------+------------------------------------------------------------------------------------------------
3819 | EPSG | 3819 | GEOGCS["HD1909",DATUM["Hungarian_Datum_1909",SPHEROID["Bessel 1841",6377397.155,299.1528128,AUTHORITY["EPSG","7004"]],TOWGS84[595.48,121.69,515.35,4.115,-2.9383,0.853,-3.408],AUTHORITY["EPSG","1024"]],PR
IMEM["Greenwich",0,AUTHORITY["EPSG","8901"]],UNIT["degree",0.0174532925199433,AUTHORITY["EPSG","9122"]],AUTHORITY["EPSG","3819"]] | +proj=longlat +ellps=bessel +towgs84=595.48,121.69,515.35,4.115,-2.9383,0.853,-3.408 +no_defs
(1 row)
Geometry in PostGIS has a different ordering of (lat long) first is going longitude then latitude.
Also if you want to transform a point from one SRID to another use st_transfrom(), not ST_SetSrid.
ST_Transform relly transform your data from one coordinates system to another.
select st_astext(st_transform(ST_SetSrid(ST_Point(11.573829,48.137969), 4326),900913))
ST_SetSrid - just change SRID for the object.
select st_astext((ST_SetSrid(ST_Point(11.573829,48.137969),900913)
So, you have to change your SQL that way
SELECT name, shop
FROM planet_osm_point
WHERE ST_DWithin(way,st_transform(ST_SetSrid(ST_Point(11.573829,48.137969), 4326),900913), 100);

JSFG grammar not parsing

I can't see where im breaking my jsfg grammar (for Sphinx4).
Or is there any debugging tool for parsing?
This compiles:
#JSGF V1.0;
grammar dialog;
<digit> = oh |
zero |
one |
two |
three |
four |
five |
six |
seven |
eight |
nine ;
<number> = <digit>+ [point <digit>+];
<menu_command> = digits |
[go to [the]] bank account |
weather forecast |
[play] music |
v |
hud |
exit [[the] program] ;
<bank_command> = [show | check] balance |
deposit <number> |
withdraw <number> |
back ;
<artist_command> = elvis |
moby |
[the] beatles |
sia |
random;
<song_command> = [a little less] converstion |
moby |
[the] beatles |
sia ;
<music_command> = [play] music;
public <command> = <menu_command> | <bank_command>;
But this doesnt:
#JSGF V1.0;
grammar dialog;
<digit> = oh |
zero |
one |
two |
three |
four |
five |
six |
seven |
eight |
nine ;
<number> = <digit>+ [point <digit>+];
<hud_command> = voicehud | hud
<menu_command> = digits |
[go to [the]] bank account |
weather forecast |
v |
hud |
exit [[the] program] |
hide ;
<bank_command> = [show | check] balance |
deposit <number> |
withdraw <number> |
back ;
<artist_command> = elvis |
moby |
[the] beatles |
sia |
random;
<song_command> = burning love |
moby |
[the] beatles |
sia ;
<album_command> = [one thousand] forms of fear |
play |
[the] white album |
burning love ;
<musicapp_command> = play | music;
<music_selector_command> = artist | song | album | random | mix;
<music_selection_command> = <artist_command> | <song_command> | <album_command>;
<music_command> = <musicapp_command><music_selector_command><music_selection_command>;
public <command> = <menu_command> | <bank_command> | <music_command>;