How to filter the SAP tables by the number of fields? - abap

SAP table DD02L lists, for each table in SAP, among others, the number of fields in each table. For example table, PLPO (PM task lists) contains 244 fields, according to T-Code S_PH0_48000138. For business reporting and using SQL, I only want to see 5, 6 field values at most, but the entire table is replicated, all 244 fields!
So, I want to know how many transparent tables consist of more than say, 20 fields. if I run the above t-code, it will take me 10 years, to do one table at a time.
Mike McNally
I am not an experienced ABAPer, so I do not know how to set this up.

Table DD02L is "only" a list of all tables in SAP. I have not found any field in this table, which would tell, how many field the actual table has.
What could be used is table DD03L (SAP table fields), which lists all fields and tables in SAP. The fields are listed by position, which means we can select all tables where a field with position 21 exists (position 21 exists = there are more than 20 fields in the table):
SELECT FROM dd02l
INNER JOIN dd03l
ON dd02l~tabname EQ dd03l~tabname AND
dd02l~as4local EQ dd03l~as4local AND
dd02l~as4vers EQ dd03l~as4vers
FIELDS dd02l~tabname
WHERE dd02l~tabclass EQ 'TRANSP' "only transparent tables
AND dd03l~position EQ '0021'
INTO TABLE #DATA(lt_dd02l).
The result (internal table lt_dd02l) will contain all the tables, which have more than 20 fields. I am on an R/3 system currently, the query took a few seconds only, but there are still over 12.000 tables with more than 20 fields.
*Answer edited after the comment from Gert Beukema (see below)

Related

optimizing PGSQL SQL search queries on big texts ('like', full text search, ... )

We have a software solution which is used by +200 customers. We recently switched to pgsql, because our former database was too slow handeling the search queries our customers use.
Our dabatabase looks like this:
TABLE A
1. ID
(+ some other fields which aren't important here)
TABLE B
This table is used to store 'data' on the items in table A. This is different for every customer. For example 'Type' can be 'CLIENTNAME' and value 'AZERTY'. One record on TABLE A can have infinite records in TABLE B. Mostly 1 record in Table A has between 5 - 10 records on Table B.
1. ID TABLE A
2. TYPE
3. VALUE
TABLE C
1. TABLE A ID
2. VERSIONNR
3. DESCRIPTION
This file has the different verions of the records in TABLE A. Each of these versions has an extended description. This can range from 0 characters to infinite.
Our problem: our customers are used on 'google-like' searching. For example: they type 'AZERTY' and we show all the records from TABLE A where the ID of TABLE A:
'AZERTY' is in the description of the most recent version of TABLE C
'AZERTY' is in one of the values of TABLE B
Additional problem: this search is a 'contains'. If they search 'ZER', they should also find the records with 'AZERTY' in it. Multiple arguments are an 'AND', if they search for 'ZER 123', we need to show all records where the description matches 'ZER' and '123' or the values match 'ZER' and '123'.
What we have done so far:
There is an option a user can check in/out whether they want to search the description or not. We mosty advice them to only search for the values and only use the description in case of need.
We make several search threads to the database for one search query, because searching all documents at once would take too much time.
Some time ago, on our former slow database engine, a collegue of mine made 'search tables', basically this is a table which contains all values on a TABLE A ID so there isn't need for any join in the SQL query when searching. It looks like this:
TABLE D
TABLE A ID
VALUES (all values from TABLE B for this TABLE A ID, seperated by a ' ')
DESCRIPTION (the description of the most recent version for this TABLE A ID)
Example record:
- 1
- ZER 123 CLIENT NAME NUMBER 7856 jsdfjklf 4556423
- DESCRIPTION CAN BE VERY LONG.
If a customer searches for 'ZER 123' this becomes:
"select TABLE_A_ID from TABLE_D where values like '%ZER%' and values like '%123%'"
Important:
Some of our customers have alot of records in TABLE A. +5.000.000, which means there are alot of records in TABLE B (+/- 50.000.000). Most of our customers have between 300.000 and 500.000 records in TABLE A.
My questions:
Is there a better / faster way to search through all the values then that search table? Without the search table i would have to make a join for every ' ' in the search argument of the customer, which will work too slow (i think?) if they have alot of records in TABLE A. For example:
select ID from TABLE_A
INNER JOIN TABLE_B Sub1 ON TABLE_A.ID = Sub1.TABLE_A_ID and Sub1.VALUE like '%ZER%'
INNER JOIN TABLE_B Sub2 on FILE_A.ID = Sub2.TABLE_A_ID and Sub2.VALUE like '%123%'
I have taken a look at the full text search in PGSQL. I don't think i can use it since you can't use it as like (= 'contains') ?
Is there any index I can use on the values (FILE B or search file) and description (FILE C or search file) to make the searches faster? I've read on it and i don't think there is any, because indexes aren't used when searching with "like '%ZER%'" ?
I hope i've explained this cleary.
Thanks in advance!
Your terminology is confusing, but I assume you mean "tables" when you write "files".
You cannot reasonably search in several tables with a single query, but you can search in several columns of a single table at the same time.
Based on your description, I would say that you need a trigram index on the concatenation of the relevant string columns in the table.

Can this table structure work or should it change

I have an existing table which is expected to work for a new piece of functionality. I have the opinion that a new table is needed to achieve the objective and would like an opinion if it can work as is, or is the new table a must? The issue is a query returning more records than it should, I believe this is why:
There is a table called postcodes. Over time this has really become a town table because different town names have been entered so it has multiple records for most postcodes. In reference to the query below the relevant fields in the postcode table are:
postcode.postcode - the actual postcode, as mentioned this is not unique
postcode.twcid - is a foreign key to the forecast table, this is not unique either
The relevant fields in the forecast table are:
forecast.twcid - identifyer for the table however not unique because there four days worth of forecasts in the table. Only ever four, newver more, never less.
And here is the query:
select * from forecast
LEFT OUTER JOIN postcodes ON forecast.TWCID = postcodes.TWCID
WHERE postcodes.postcode = 3123
order by forecast.twcid, forecast.theDate;
Because there are two records in the postcode table for 3123 the results are doubled up. Two forecasts for day 1, two for day 2 etc......
Given that the relationship between postcodes and forecast is many to many (there are multiple records in the postcode tables for each postcode and twcid. And there are multiple records for each twcid in the forecast table because it always holds four days worth of forecasts) is there a way to re-write the query to only get four forecast records for a post code?
Or is my thought of creating a new postcode table which has unique records for each post code necessary?
You have a problem that postcodes can be in multiple towns. And towns can have multiple postcodes. In the United States, the US Census Bureau and the US Post Office have defined very extensive geographies for various coding schemes. The basic idea is that a zip code has a "main" town.
I would suggest that you either create a separate table with one row per postcode and the main town. Or, add a field to your database indicating a main town. You can guarantee uniqueness of this field with a filtered index:
create unique index postcode_postcode_maintown on postcodes(postcode) where IsMainTown = 1;
You might need the same thing for IsMainPostcode.
(Filtered indexes are a very nice feature in SQL Server.)
With this construct, you can change your query to:
select *
from forecast LEFT OUTER JOIN
postcodes
ON forecast.TWCID = postcodes.TWCID and postcodes.IsMainPostcode = 1
WHERE postcodes.postcode = 3123
order by forecast.twcid, forecast.theDate;
You should really never have a table without a primary key. Primary keys are, by definition, unique. The primary key should be the target for your foreign keys.
You're having problems because you're fighting against a poor database design.

Creating a database structure where one column has multiple values?

I have a SQL database that uses MS Access as a front-end and is coded with VB. Data is imported daily from an Excel spreadsheet in the form:
Journal Date, IO Account, Amount, Posted Date, Line Description, User ID, Date Checked, Voucher
The Voucher data is formatted in the Excel spreadsheet like:
1111111;2222222;3333333
The Voucher can have as many voucher numbers as needed (anywhere from 1 - 13 different num bers usually) and each number is separated by a semi-colon. Also, each number can differ in physical length. I then need to link these voucher numbers to multiple different tables. The data structure that was in place when I took over this project stored the voucher in the semi-colon separated form and parsed the string to link to other tables. I'm getting ready to revamp this database, and I don't want to store the data like this format because I know it violates 1NF.
I know I should probably use foreign keys, but I'm not sure how with the varying Voucher data. I have the ability to parse the data any way possible with VB in Access when it comes from Excel, I just don't know how to store it to relate my tables.
The goal of the project is to match everthing that relates to each distinct voucher and see if the amounts match up. Right now the process takes anywhere from 5 - 10 minutes to split the vouchers and compare the data across tables.
Let me know if you need more information. Any advice would be appreciated.
Thanks!
EDIT- Let me be more clear:
Here is an example voucher: 2988670;2990020;2989130;2991597;ONL112382
There are multiple entries in the table (call it T1) with this voucher with differing amounts. Each of the numeric values (excluding ONL number) correspond to another table (call it T2). If each of these 4 numbers are in T2, they are said to be "Matching". If they are matching and the sum of the amounts in T2 equal the sum of the amounts in T1, they are "Matching with no difference".
Sometimes the voucher looks like this: ED414596
In this case, I have to compare this value to a completely different table (call it T3). It includes the same matching process as above.
*Let's just say the voucher comes across in multiple ways and it needs to be compared to multiple tables.
Your voucher table would have a voucherID and a voucherNumber, this would allow voucherID to be repeated as many times as necessary. voucherID would be a foreign key from your first table, and the two columns together would be the PK for this table.

Oracle SQL Select from a Large Number of Tables

I apologize if this has been answered elsewhere (There has to be something out there on the topic), but I can't seem to find a concise answer to my question.
I am relatively new to SQL, and when I have worked with it I have only used basic statements. Now I am working with a pretty large database (in Oracle) and was asked to explore it a little bit on the development side to get more familiar.
One of the questions that was sent to me to explore the db involved finding a list of "Run Controls" that are associated with a particular user.
There is a single table that keeps track of the different types of "Run Controls" that exist via a field titled run_cntl_id. There are 18 rows in this table associated with the specific user, each with a unique run_cntl_id. For each of the values in the run_cntl_id field, there is at least one corresponding table with multiple rows (pretty standard database stuff). Unfortunately, I do not have any reference material to display the table relationships.
There are just under 3,000 tables that contain both the oprid (the user identifier) and the run_cntl_id (the type of "Run Control") fields (when they are separated, there are 3,100 tables that contain the run_cntl_id field, and 8,800 that contain the oprid field). There are approximately 65,000 total tables in the database. Is there a way to search these 3,000 tables for the specific operid and run_cntl_id?
If I wanted to perform this query on one table, I would use the following statement:
SELECT *
FROM PS_JRNL_COPY_REQ
WHERE oprid = 'jle0010'
AND run_cntl_id = 'Copy_Jrnl';
To rephrase the question:
Is there a way to perform this statement on the 3,000 tables mentioned above without running a single statement 3,000 times?
If all of the 3,000 tables have the same columns then your query is going to look like :
SELECT *
FROM (
select * from PS_JRNL_COPY_REQ union all
select * from other_table_1 union all
select * from other_table_2 union all
... and so on for 2,997 more)
WHERE oprid = 'jle0010'
AND run_cntl_id = 'Copy_Jrnl';
No guarantees on it parsing or running though.
You can build that inline view by querying user_tables of course.

How to find number of observations in postgresql tables

I am from DW/BI background using SAS for many years now I have task to find out number of records present in tables on the fly for postgresql tables
i.e. In SAS we have meta tables which has details about tables and no of records, column info etc in system meta tables in a same manner is there any meta table available in postgresql to get no of observation on the fly?
I know we can do select count(*) from table but I don't want to do that, I want to know is there any built in meta tables in postgresql to get no of records present in table?
Highly appreciated your help.
The pg_class system catalogue contains information about each relation (table, index, view, sequence...). For tables, this includes an estimate of the number of tuples (rows) and disk pages taken up by the table. e.g.:
SELECT reltuples, relpages FROM pg_class WHERE oid = 'table_name'::regclass
Note that reltuples is of "real" type and so stores about 6 significant figures.