Fetch a single field from DB table into itab - abap

I want to fetch the a field say excep_point from a transparent table z_accounts for the combination of company_code and account_number. How can I do this in ABAP SQL?
Assume that table structure is
|company_code | account_number | excep_point |

Assuming you have the full primary key...
data: gv_excep_point type zaccounts-excep_point.
select single excep_point
into gv_excep_point
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
if you don't have the full PK and there could be multiple values for excep_point
data: gt_excep_points type table of zaccounts-excep_point.
select excep_point
into table gt_excep_points
from zaccounts
where company_code = some_company_code
and account_number = some_account_number.
There is at least another variation, but those are 2 I use most often.

For information only. When you selects data into table you can write complex expressions to combine different fields. For example, you have internal table (itab) with two fields "A" and "B". And you are going to select data from DB table (dbtab) wich have 6 columns - "z","x","y","u","v","w". And for example each field is type char2 You aim to cimbine "z","x","y","u" in "A" field of internal table and "v","w" in "B" field. You can write simple code:
select z as A+0(2)
x as A+2(2)
y as A+4(2)
u as A+6(2)
v as B+0(2)
w as B+2(2) FROM dbtab
INTO CORRESPONDING FIELDS OF TABLE itab
WHERE <where condition>.
This simple code makes you job done very simple

In addition to Bryans answer, here is the official online documentation about Open SQL.

Related

Get data from other table based on column with concatenated values

I have two tables:
category with columns:
id name
1 business
2 sports
...
article with columns:
id title categories
1 abc 1|2|3
2 xyz 1|2
I know there should be a separate table for article categories but I was given this.
Is it possible to write a query that returns:
id title category_names
1 xyz business,sports
I thought of splitting the string in article -> categories column, then use in query to extract name from category table but couldn't figure it out.
You should fix your data model. But, you can do this in SQL Server:
select a.*, s.names
from article a cross apply
(select string_agg(c.name, ',') as names
from string_split(a.categories, '|') ss join
category c
on try_convert(int, ss.value) = c.id
) s;
Here is a db<>fiddle.
Presumably, you already know the shortcomings of this data model:
SQL Server has poor string handling functionality.
Numbers should be stored as numbers not strings.
Foreign key references should be properly declared.
Such queries cannot make use of indexes and partitions.
If you really want to store multiple values in a field, SQL Server offers both JSON and XML. Strings are not the right approach.

Access Append Query compare with table

I am currently rebuilding a messy Access Database and I entcountered the following problem:
I've got a Table of facilities which contain a row called district. Those Rows contain a number linked to another table which just contains the numbers and names of districts. I added a lookup Column with the Name of the district displayed.
I now want to change the new column for every row depending on the data in the old row.
Facilities
NAME|..|DISTRICT_OLD
A |..| 1
B |..| 2
C |..| 1
...
DISTRICTS
ID|NAME
1 |EAST
2 |WEST
...
I would like something like the following:
Facilities
NAME|..|DISTRICT_OLD|DISTRICT
A |..| 1|EAST
B |..| 2|WEST
C |..| 1|EAST
...
The District Field (lookup) gets its Data like follows SELECT [DISTRICTS].ID, [DISTRICTS].NAME FROM DISTRICTS ORDER BY [NAME];
(Thanks to Gordon Linoff) I could get the query but I do now struggle with the insert. I can get the Data I want:
SELECT [DISTRICTS].NAME FROM Facilities INNER JOIN DISTRICTS ON Facilities.DISTRICT_OLD = [DISTRICTS].ID;
If I try to INSERT INTO Facilities(DISTRICT) It says Typerror.
How can I modify the data to be compatible with a lookup column?
I guess I need to select the ID as well which isnt't a problem but then the error says to many columns.
I hope I haven't mistaken any names, my Access isn't running the english language.
Can you help me?
Fabian
Lookup columns are number (long integer)
with a relational database, you only need the single column containing the ID (as you always lookup the district.name with a query) so:
INSERT INTO Facilities(DISTRICT) SELECT 4
where 4 is the ID of the record in the lookup table that you want, or better still:
INSERT INTO Facilities(DISTRICT)
SELECT ID FROM DISTRICTS
where District.Name = "Name you want the ID for"

Dividing one column into two, then joining new columns with other tables

I have a DB with three tables.
"Campaign" table has a column "Campaign number" (e.g. value = 1)
"Payment" table has a column "user_id" (e.g. value = 134356)
"User_Source" table has a column "dump" which contains both the user id and campaign number: info_u134356_cpn_1 OR info_cpn_1_u134356
I need to divide the data from the combined values in user_source, so that I would be able to see user_id and their linked campaign number in one table, and then count how many users are attributed to each campaign.
I can't get my head around the way to split ths column, and whether there is a way to do s without spitting (e.g. somehow filtering).
I'm currently using DataGrip for this.
You can use regexp_match() in Postgres:
with sample (dump) as (
values
('info_cpn_1_u134356'),
('info_u456789_cpn_5')
)
select (regexp_match(dump, 'u([0-9]+)'))[1] as user_id,
(regexp_match(dump, 'cpn_([0-9]+)'))[1] as campaign
from sample;
returns:
user_id | campaign
--------+---------
134356 | 1
456789 | 5

Tricky PostgreSQL join and order query

I've got four tables in a PostgreSQL 9.3.6 database:
sections
fields (child of sections)
entries (child of sections)
data (child of entries)
CREATE TABLE section (
id serial PRIMARY KEY,
title text,
"group" integer
);
CREATE TABLE fields (
id serial PRIMARY KEY,
title text,
section integer,
type text,
"default" json
);
CREATE TABLE entries (
id serial PRIMARY KEY,
section integer
);
CREATE TABLE data (
id serial PRIMARY KEY,
data json,
field integer,
entry integer
);
I'm trying to generate a page that looks like this:
section title
field 1 title | field 2 title | field 3 title
entry 1 | data 'as' json | data 1 json | data 3 json <-- table
entry 2 | data 'df' json | data 5 json | data 6 json
entry 3 | data 'gh' json | data 8 json | data 9 json
The way I have it set up right now each piece of 'data' has an entry it's linked to, a corresponding field (that field has columns that determine how the data's json field should be interpreted), a json field to store different types of data, and an id (1-9 here in the table).
In this example there are 3 entries, and 3 fields and there is a data piece for each of the cells in between.
It's set up like this because one section can have different field types and quantity than another section and therefore different quantities and types of data.
Challenge 1:
I'm trying to join the table together in a way that it's sortable by any of the columns (contents of the data for that field's json column). For example I want to be able to sort field 3 (the third column) in reverse order, the table would look like this:
section title
field 1 title | field 2 title | field 3 title
entry 3 | data 'gh' json | data 8 json | data 9 json
entry 2 | data 'df' json | data 5 json | data 6 json
entry 1 | data 'as' json | data 1 json | data 3 json <-- table
I'm open to doing it another way too if there's a better one.
Challenge 2:
Each field has a 'default value' column - Ideally I only have to create 'data' entries when they have a value that isn't that default value. So the table might actually look like this if field 2's default value was 'asdf':
section title
field 1 title | field 2 title | field 3 title
entry 3 | data 'gh' json | data 8 json | data 9 json
entry 2 | data 'df' json | 'asdf' | data 6 json
entry 1 | data 'as' json | 'asdf' | data 3 json <-- table
The key to writing this query is understanding that you just need to fetch all the data for single section and the rest you just join. You also can't with your schema directly filter data by section so you'll need to join entry just for that:
SELECT d.* FROM data d JOIN entries e ON (d.entry = e.id)
WHERE e.section = ?
You can then join field to each row to get defaults, types and titles:
SELECT d.*, f.title, f.type, f."default"
FROM data d JOIN entries e ON (d.entry = e.id)
JOIN fields f ON (d.field = f.id)
WHERE e.section = ?
Or you can select fields in a separate query to save some network traffic.
So this was an answer, here come bonuses:
Use foreign keys instead of integers to refer to other tables, it will make database check consistency for you.
Relations (tables) should be called in singular by convention, so it's section, entry and field.
Referring fields are called <name>_id, e.g. field_id or section_id also by convention.
The whole point of JSON fields is to store a collection with not statically defined data, so it would made much more sense to not use entries and data tables, but single table with JSON containing all the fields instead.
Like this:
CREATE TABLE row ( -- less generic name would be even better
id int primary key,
section_id int references section (id),
data json
)
With data fields containing something like:
{
"title": "iPhone 6",
"price": 650,
"available": true,
...
}
#Suor has provided good advice, some of which you already accepted. I am building on the updated schema.
Schema
CREATE TABLE section (
section_id serial PRIMARY KEY,
title text,
grp integer
);
CREATE TABLE field (
field_id serial PRIMARY KEY,
section_id integer REFERENCES section,
title text,
type text,
default_val json
);
CREATE TABLE entry (
entry_id serial PRIMARY KEY,
section_id integer REFERENCES section
);
CREATE TABLE data (
data_id serial PRIMARY KEY,
field_id integer REFERENCES field,
entry_id integer REFERENCES entry,
data json
);
I changed two more details:
section_id instead of id, etc. "id" as column name is an anti-pattern that's gotten popular since a couple of ORMs use it. Don't. Descriptive names are much better. Identical names for identical content is a helpful guideline. It also allows to use the shortcut USING in join clauses:
Don't use reserved words as identifiers. Use legal, lower-case, unquoted names exclusively to make your life easier.
Are PostgreSQL column names case-sensitive?
Referential integrity?
There is another inherent weakness in your design. What stops entries in data from referencing a field and an entry that don't go together? Closely related question on dba.SE
Enforcing constraints “two tables away”
Query
Not sure if you need the complex design at all. But to answer the question, this is the base query:
SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
FROM entry e
JOIN field f USING (section_id)
LEFT JOIN data d USING (field_id, entry_id) -- can be missing
WHERE e.section_id = 1
ORDER BY 1, 2;
The LEFT JOIN is crucial to allow for missing data entries and use the default instead.
SQL Fiddle.
crosstab()
The final step is cross tabulation. Cannot show this in SQL Fiddle since the additional module tablefunc is not installed.
Basics for crosstab():
PostgreSQL Crosstab Query
SELECT * FROM crosstab(
$$
SELECT entry_id, field_id, COALESCE(d.data, f.default_val) AS data
FROM entry e
JOIN field f USING (section_id)
LEFT JOIN data d USING (field_id, entry_id) -- can be missing
WHERE e.section_id = 1
ORDER BY 1, 2
$$
,$$SELECT field_id FROM field WHERE section_id = 1 ORDER BY field_id$$
) AS ct (entry int, f1 json, f2 json, f3 json) -- static
ORDER BY f3->>'a'; -- static
The tricky part here is the return type of the function. I provided a static type for 3 fields, but you really want that dynamic. Also, I am referencing a field in the json type that may or may not be there ...
So build that query dynamically and execute it in a second call.
More about that:
Dynamic alternative to pivot with CASE and GROUP BY

help in sql command .. i want list names which have defined id s

i have table consist of columns : id,name,job
and i have row stored with this data :
id: 1
name : jason
job: 11,12
id: 2
name : mark
job: 11,14
i want write sql command to fetch names which have value "14" stored in job column only from this table
so how i do that ?
thanks
You can do:
WHERE FIND_IN_SET(14, job)
But that is really not the correct way. The correct way is to normalize your database and separate the job field into its own table. Check this answer for extra information:
PHP select row from db where ID is found in group of IDs
You shouldn't be storing multiple job ids in the same field. You want to normalise your data model. Remove the 'job' column from your names table, and have a second JOB table defined like this:
id | name_id | job_id
1 1 11
2 1 12
3 2 11
4 2 14
where name_id is the primary id ('id') of the entry in the names table.
Then you can do:
SELECT name_id, job_id FROM JOB WHERE name_id = 1;
for example. As well as making your data storage far more extensible - you can now assign unlimited numbers of job_ids to each name for example - it'll also be much faster to execute queries as all your entries are now ints and no string processing is required.
SELECT
*
FROM
MyTable
WHERE
job LIKE '14,%' OR job LIKE '%,14' OR job LIKE '%,14,%'
EDIT: Thanks to onedaywhen
SELECT
*
FROM
MyTable
WHERE
(',' + job + ',') LIKE ('%,14,%')