Search for row where email contains only the X character - sql-server

I want to search for rows whose column email has only the X character.
For example, if the email is XXXX, it should fetch the row but if the email is XXX#XXX.COM it should not be fetched.
I have tried something like this, but it is returning me all emails having the character X in it:
select *
from STUDENTS
where EMAIL like '%[X+]%';
Any idea what is wrong with my query?
Thanks

Try below query:
select *
from STUDENTS
where LEN(EMAIL) > 0 AND LEN(REPLACE(EMAIL,'X','')) = 0;

I would use PATINDEX:
SELECT * FROM STUDENTS WHERE PATINDEX('%[^X]%', Email)=0
Only X means no other characters than X.
To handle NULLs and empty strings you should consider additional conditions. See demo below:
WITH STUDENTS AS
(
SELECT * FROM (VALUES ('XXXX'),('XXX#XXX.COM'),(NULL),('')) T(Email)
)
SELECT *
FROM STUDENTS
WHERE PATINDEX('%[^X]%', Email)=0 AND LEN(Email)>0

This will find all rows where email only contain 1 or more X and no other characters.
SELECT *
FROM STUDENTS
WHERE Email not like '%[^X]%' and Email <> ''

Related

Return Parts of an Array in Postgres

I have a column (text) in my Postgres DB (v.10) with a JSON format.
As far as i now it's has an array format.
Here is an fiddle example: Fiddle
If table1 = persons and change_type = create then i only want to return the name and firstname concatenated as one field and clear the rest of the text.
Output should be like this:
id table1 did execution_date change_type attr context_data
1 Persons 1 2021-01-01 Create Name [["+","name","Leon Bill"]]
1 Persons 2 2021-01-01 Update Firt_name [["+","cur_nr","12345"],["+","art_cd","1"],["+","name","Leon"],["+","versand_art",null],["+","email",null],["+","firstname","Bill"],["+","code_cd",null]]
1 Users 3 2021-01-01 Create Street [["+","cur_nr","12345"],["+","art_cd","1"],["+","name","Leon"],["+","versand_art",null],["+","email",null],["+","firstname","Bill"],["+","code_cd",null]]
Disassemble json array into SETOF using json_array_elements function, then assemble it back into structure you want.
select m.*
, case
when m.table1 = 'Persons' and m.change_type = 'Create'
then (
select '[["+","name",' || to_json(string_agg(a.value->>2,' ' order by a.value->>1 desc))::text || ']]'
from json_array_elements(m.context_data::json) a
where a.value->>1 in ('name','firstname')
)
else m.context_data
end as context_data
from mutations m
modified fiddle
(Note:
utilization of alphabetical ordering of names of required fields is little bit dirty, explicit order by case could improve readability
resulting json is assembled from string literals as much as possible since you didn't specified if "+" should be taken from any of original array elements
the to_json()::text is just for safety against injection
)

I need to show all data form pinjaman_id but only last data in every pinjaman_id form database

I'm using laravel, I want to make show all last data based on pinjaman_id this mean I only need last data of pinjaman_id, so pinjaman_id cant show duplicate, I just need the last one, and show them all last data with diffirent pinjaman_id
$pinjaman = DB::table('invoice')->where('pinjaman_id', 67)->orderBy('tgl_tempo', 'desc')->first();
if I'm using this, its only show last data in pinjaman_id = 67, I need to show them all but only last data based on tgl_tempo desc
$pinjaman = DB::table('invoice')->where('pinjaman_id', ??)->orderBy('tgl_tempo', 'desc')->first();
this is image my database
You have to use raw query to get the correct data then use UNION ALL to get other data
$results = DB::select("(SELECT * FROM invoice WHERE pinjaman_id= 67 order by tgl_tempo DESC limit 1) UNION ALL (SELECT * FROM invoice WHERE pinjaman_id != 67)") ;
try this one
$query = "select * from invoice where id IN (select MAX(id) from invoice where user_id = :userId group by pinjaman_id) order by tgl_tempo desc ";
$result = DB::select(DB::raw($query),['userId' => 1]);

replace not working after specific number

I have a table with a column vouchn. The recod of this column eg-if it receipt voucher it will record like RV103 AND LIKE payment it stores like PV99. I also use this sql for gettin max records.
SELECT MAX(REPLACE(vouchn, 'RV', '')) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')
it is ok until i reach RV999. After then even record RV1000 is there the above sql retrieve RV999. What is the error of the above code.
If REPLACE(vouchn, 'RV', '') always return numeric result, you can as the below:
SELECT MAX(REPLACE(vouchn, 'RV', '') * 1) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')
Add CONVERT to numeric type:
SELECT MAX(CONVERT(BIGINT,REPLACE(vouchn, 'RV', ''))) AS vcno
FROM dbo.dayb
WHERE (vouchn LIKE '%RV%')

Removing the repeating elements from a row in a squlite table

Please let me know if there is any query where in I remove the repeating entries in a row.
For eg: I have a table which has name with 9 telephone numbers:
Name Tel0 Tel1 Tel2 Tel3 Tel4 Tel5 Tel6 Tel7 Tel8
John 1 2 2 2 3 3 4 5 1
The final result should be as shown below:
Name Tel0 Tel1 Tel2 Tel3 Tel4 Tel5 Tel6 Tel7 Tel8
John 1 2 3 4 5
regards
Maddy
I fear that it will be more complicated to keep this format than to split the table in two as I suggested. If you insist on keeping the current schema then I would suggest that you query the row, organise the fields in application code and then perform an update on the database.
You could also try to use SQL UNION operator to give you a list of the numbers, a UNION by default will remove all duplicate rows:
SELECT Name, Tel FROM
(SELECT Name, Tel0 AS Tel FROM Person UNION
SELECT Name, Tel1 FROM Person UNION
SELECT Name, Tel2 FROM Person) ORDER BY Name ;
Which should give you a result set like this:
John|1
John|2
You will then have to step through the result set and saving each number into a separate variable (skipping those variables that do not exist) until the "Name" field changes.
Tel1 := Null; Tel2 := Null;
Name := ResultSet['Name'];
Tel0 := ResultSet['Tel'];
ResultSet.Next();
if (Name == ResultSet['Name']) {
Tel1 := ResultSet['Tel'];
} else {
UPDATE here.
StartAgain;
}
ResultSet.Next();
if (Name == ResultSet['Name']) {
Tel2 := ResultSet['Tel'];
} else {
UPDATE here.
StartAgain;
}
I am not recommending you do this, it is very bad use of a relational database but once implemented in a real language and debugged that should work.

Only the last entry is selected to itab

At my selection Screen you can choose with a radio button Group with which kind of number you want to select the information. (material number, construction contract or customer order).
After choosing a kind, the User have to fill in the number(s) into the corresponding select option.
With this information I select the information I need an move them to the itab t_marc. This table has the same fields as marc.
When the User choose material number at the selection screen everything works fine and the values to every number the user wrote down is displayed at the ALV-List.
When selecting by one of the other numbers, the values in output are also right, but only the information to the last denoted number will be edited.
How can I move all numbers to my itabs?
PARAMETERS: p_mat RADIOBUTTON GROUP radi.
PARAMETERS: p_auf RADIOBUTTON GROUP radi.
PARAMETERS: p_vbl RADIOBUTTON GROUP radi.
SELECT-OPTIONS: s_matnr FOR marc-matnr.
SELECT-OPTIONS: s_aufnr FOR aufk-aufnr.
SELECT-OPTIONS: s_vbeln FOR vbap-vbeln.
start-of-selection
IF p_mat = 'X'.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr IN s_matnr
AND werks = p_werks.
ELSEIF p_auf = 'X'.
SELECT * FROM afpo
INTO TABLE t_afpo
WHERE aufnr IN s_aufnr.
LOOP AT t_afpo.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
ENDLOOP.
ELSEIF p_vbl = 'X'.
SELECT * FROM vbap
INTO TABLE t_vbap
WHERE vbeln = s_vbeln-low
AND posnr IN s_posnr.
LOOP AT t_vbap.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_vbap-matnr
AND werks = p_werks.
ENDLOOP.
You're overwriting the records every time in this loop (and the similar loops).
LOOP AT t_afpo.
SELECT * FROM marc
INTO TABLE t_marc
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
ENDLOOP.
"INTO TABLE" overwrites every time. You could switch to "APPENDING TABLE." Alternatively, I would use a for all entries select instead (no loop).
SELECT * FROM marc
INTO TABLE t_marc
FOR ALL ENTRIES IN t_afpo
WHERE matnr = t_afpo-matnr
AND werks = p_werks.
Always make sure there are records in the driver table (in this case, t_afpo) or you will have performance issues.

Resources