Define Column Aliases? - sql

I have a query like this:
SELECT `*`
FROM (`threads` t, `members` m)
WHERE `m`.`id` = t.author
AND `t`.`type` = '0'
AND `t`.`category` = '1'
And basically what happens is that there is an ID field in both tables (members and threads) so what's happening is that the results array is getting messed up. IE: There is only one ID field which is being populated from the members table.
What I need to do is make the results with a prefix infront of their key name so I can distinguish between the two:
IE: Add 't.' to all thread fields and 'm.' to all members fields.
So results should be like: m.id = x, t.id = y
Instead, results at the moment are like: id = x (the id field from the thread table is completely overwritten by the one from the members table)

You could do it by naming each column one by one:
SELECT m.`id` AS "m_id", `t`.`id` AS "t_id", t.`username` AS "t_username"
FROM (`threads` t, `members` m)
WHERE `m`.`id` = t.author
AND `t`.`type` = '0'
AND `t`.`category` = '1'

Use:
SELECT m.id AS x,
t.id 'y'
FROM MEMBERS m
JOIN THREADS t ON t.id = m.author
AND t.type = '0'
AND t.category = '1'
Column aliases are defined on a column by column basis - you can't use wildcards/etc.
You can use the AS keyword, or simply enclose the column alias within single quotes if the column name doesn't contain special characters - use double quotes if it does. You can combine single/double quote usage with the AS keyword.
Do I have to List all the Columns?
Yes, you have to list all the columns unless you like duplicate columns because you choose to use m.* or t.*. There is no convention in SQL that supports what you ask. SELECT * is not an ideal practice - read this answer for details beyond this situation why.
Addendum
I took the liberty of rewriting your query to use ANSI-92 JOIN syntax - your example used ANSI-89. There's no performance difference.

You can set an alias for columns that have the same name:
SELECT t.ID as threadsID, m.ID as membersID, <...> WHERE `m`.`id` = t.author AND `t`.`type` = '0' AND `t`.`category` = '1'

If you just want the id's to be separate, you can do
SELECT `*`, t.id as t_id, m.id as m_id
FROM (`threads` t, `members` m)
WHERE `m`.`id` = t.author
AND `t`.`type` = '0'
AND `t`.`category` = '1'
As the others said, it's a column alias.

Related

IF / Case statment in SQL

I have a column where I have 0 or 1. I like to do the following set up:
If 0 than put / use the Region_table (here I have regions like EMEA, AP,LA with finished goods only) and when it 1 then put / use the Plant_table (here I have plants with non-finished goods) data's.
I tried to write it in 2 different statements but it is not good:
,Case
when [FG_NFG_Selektion] = '0' Then 'AC_region'
End as 'AC_region'
,Case
when [FG_NFG_Selektion] = '1' Then 'AC_plant'
End as 'AC_plant'
I'm not 100% clear on what you're looking for, but if you want to get data from different tables based on the value in the [FG_NFG_Selektion] field, you can do something like this:
SELECT
CASE
WHEN [FG_NFG_Selektion] = '0' THEN r.some_col -- If 0, use value from "region" table
WHEN [FG_NFG_Selektion] = '1' THEN p.some_col -- If 1, use value from "plant" table
END AS new_field
FROM MyTable t
LEFT JOIN AC_region r ON t.pk_col = r.pk_col -- get data from "AC_region" table
LEFT JOIN AC_plant p ON t.pk_col = p.pk_col -- get data from "AC_plant" table
;
If [FG_NFG_Selektion] is a numeric field, then you should remove the single quotes: [FG_NFG_Selektion] = 0.
I would strongly recommend putting the conditions in the ON clauses:
SELECT COALESCE(r.some_col, p.some_col) as som_col
FROM t LEFT JOIN
AC_region r
ON t.pk_col = r.pk_col AND
t.FG_NFG_Selektion = '0' LEFT JOIN
AC_plant p
ON t.pk_col = p.pk_col AND
t.FG_NFG_Selektion = '1';
Why do I recommend this? First, this works correctly if there are multiple matches in either table. That is probably not an issue in this case, but it could be in others. You don't want to figure out where extra rows come from.
Second, putting the conditions in the ON clause allows the optimizer/execution engine to take advantage of them. For instance, it is more likely to use FG_NFG_Selektion in an index.

how to filter record which contains exactly two values in a table in sql?

When I use IN, it shows all records contains parameter1 or parameter2, but I want it bring to records contains exactly both of them, not just one of them.
If my question is not clear, I can try to explain again.
select Hatlar.Name
from HATLAR,
[HAT-DURAK],
DURAKLAR
where HATLAR.Hat_Id = [HAT-DURAK].Hat_Id
and DURAKLAR.Durak_Id = [HAT-DURAK].Durak_Id
and DURAKLAR.Name IN ('parameter1', 'parameter2')
Do a GROUP BY. Use having count distinct to make sure both DURAKLAR.Names are there.
select Hatlar.Name
from HATLAR,
[HAT-DURAK],
DURAKLAR
where HATLAR.Hat_Id = [HAT-DURAK].Hat_Id
and DURAKLAR.Durak_Id = [HAT-DURAK].Durak_Id
and DURAKLAR.Name IN ('parameter1', 'parameter2')
group by Hatlar.Name
having count(distinct DURAKLAR.Name) = 2
First, learn to use proper JOIN syntax. Commas in the FROM clause are soooo 20th century.
Second, you can do what you want with GROUP BY and HAVING:
Select h.Name
from HATLAR h join
[HAT-DURAK] hd
on h.Hat_Id = hd.Hat_Id join
DURAKLAR d
on d.Durak_Id = d.Durak_Id
where d.Name IN ('parameter1', 'parameter2')
group by n.Name
having count(d.Name) = 2;
Note: If duplicates can appear in the junction table, then use count(distinct d.Name).
If I understand the question, this should work (assuming the parameters are actually that, and not hard coded strings):
select Hatlar.Name
from HATLAR,
[HAT-DURAK],
DURAKLAR
where HATLAR.Hat_Id = [HAT-DURAK].Hat_Id
and DURAKLAR.Durak_Id = [HAT-DURAK].Durak_Id
and DURAKLAR.Name Like '%' + #parameter1 + '%'
and DURAKLAR.Name Like '%' + #parameter2 + '%'

How to use a variable AS a where clause?

I have one where clause which I have to use multiple times. I am quite new to Oracle SQL, so please forgive me for my newbe mistakes :). I have read this website, but could not find the answer :(. Here's the SQL statement:
var condition varchar2(100)
exec :condition := 'column 1 = 1 AND column2 = 2, etc.'
Select a.content, b.content
from
(Select (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3)) as content
from table_name
where category = X AND :condition
group by (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3))
) A
,
(Select (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,100)) as content
from table_name
where category = Y AND :condition
group by (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,100))) B
GROUP BY
a.content, b.content
The content field is a CLOB field and unfortunately all values needed are in the same column. My query does not work ofcourse.
You can't use a bind variable for that much of a where clause, only for specific values. You could use a substitution variable if you're running this in SQL*Plus or SQL Developer (and maybe some other clients):
define condition = 'column 1 = 1 AND column2 = 2, etc.'
Select a.content, b.content
from
(Select (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3)) as content
from table_name
where category = X AND &condition
...
From other places, including JDBC and OCI, you'd need to have the condition as a variable and build the query string using that, so it's repeated in the code that the parser sees. From PL/SQL you could use dynamic SQL to achieve the same thing. I'm not sure why just repeating the conditions is a problem though, binding arguments if values are going to change. Certainly with two clauses like this it seems a bit pointless.
But maybe you could approach this from a different angle and remove the need to repeat the where clause. Querying the table twice might not be efficient anyway. You could apply your condition once as a subquery, but without knowing your indexes or the selectivity of the conditions this could be worse:
with sub_table as (
select category, content
from my_table
where category in (X, Y)
and column 1 = 1 AND column2 = 2, etc.
)
Select a.content, b.content
from
(Select (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3)) as content
from sub_table
where category = X
group by (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3))
) A
,
(Select (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,100)) as content
from sub_table
where category = Y
group by (DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,100))) B
GROUP BY
a.content, b.content
I'm not sure what the grouping is for - to eliminate duplicates? This only really makes sense if you have a single X and Y record matching the other conditions, doesn't it? Maybe I'm not following it properly.
You could also use a case statement:
select max(content_x), max(content_y)
from (
select
case when category = X
then DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,3) end as content_x,
case when category = Y
then DBMS_LOB.SUBSTR(ost_bama_vrij_veld.inhoud,100) end as content_y,
from my_table
where category in (X, Y)
and column 1 = 1 AND column2 = 2, etc.
)

Simple SQL query too long

I just have a simple query. On SQL Server 2008, sometimes it queries too long, nearly hang, sometimes not. The same sql on Oracle server, it always return at once.
SELECT D.DESCITEM, D.LONGDESC, D.DESCTABL, D.DESCCOY, D.DESCPFX
FROM VM1DTA.DESCPF D, VM1DTA.ITEMPF I
WHERE D.DESCPFX='IT'AND D.DESCITEM=I.ITEMITEM AND I.VALIDFLAG='1'
AND D.DESCTABL = I.ITEMTABL AND D.DESCCOY = I.ITEMCOY AND "LANGUAGE" = 'E'
AND "VALIDFLAG" = '1' AND DESCTABL IN('T1680')
ORDER BY LONGDESC ASC;
Each table has about 100k records.
Could someone point me about the root cause? Thanks
I'm not sure what the issue is but your query could use some refactoring. This line looks unneeded as well "VALIDFLAG" = '1' because it has no prefix. The IN may have something to do with it.
SELECT D.DESCITEM, D.LONGDESC, D.DESCTABL, D.DESCCOY, D.DESCPFX
FROM
VM1DTA.DESCPF D INNER JOIN VM1DTA.ITEMPF I ON
D.DESCITEM=I.ITEMITEM
AND
D.DESCTABL = I.ITEMTABL
AND
D.DESCCOY = I.ITEMCOY
WHERE
D.DESCPFX='IT'
AND
"LANGUAGE" = 'E'
AND
I.VALIDFLAG='1'
AND
"VALIDFLAG" = '1'
AND
I.DESCTABL = 'T1680'
ORDER BY
LONGDESC ASC;
The other thing to look at is putting indexes on all of the join columns.
Hope this helps.
I find that joining two tables by free text fields takes up a lot of resource and time. Additionally these fields are traditionally not indexed in anyway.
Try to see if there are any indexes worth using instead or other joins.
Also your join to the I.ITEMTABL field is not required as the D.DESCTBL field has a filter making the processor work more to join the two, unless it's an index.
Another method would be to use a subquery in your where clause like:
SELECT D.DESCITEM, D.LONGDESC, D.DESCTABL, D.DESCCOY, D.DESCPFX
FROM VM1DTA.DESCPF D
WHERE D.DESCPFX = 'IT'
AND D.LANGUAGE = 'E'
AND D.VALIDFLAG = '1'
AND D.DESCTABL = 'T1680'
AND EXISTS (SELECT NULL
FROM VM1DTA.ITEMPF I
WHERE I.VALIDFLAG = '1'
AND I.ITEMTBL = 'T1680'
AND D.DESCITEM = I.ITEMITEM
AND D.DESCCOY = I.ITEMCOY)
ORDER BY LONGDESC ASC;

Joining tables based on values from other tables

I have the following tables. I want to run a query but I think my beginner tsql level won't help here.. It probably also is a situation where I have a bad database design.
Basically I need to select all fields from tblPhotoGalleries. Also I need to create a seperate field named GalleryCategoryName.
GalleryCategoryName field will be the pCatName in tblPhotoGalleryCats.
If pCatName in tblPhotoGalleryCats = '0', then that would mean, ConnectedNewsCatID is something other than 0. In that case;
GalleryCategoryName will be the CategoryName field from tblNewsCategories where CategoryID = ConnectedNewsCatID
Use a left join on the news category table, and use a case expression to choose between the names:
select
g.pgID, g.gName,
GalleryCategoryName = case c.pCatName when '0' then n.CategoryName else c.pCatName end
from tblPhotoGalleries g
inner join tblPhotoGFalleryCats c on c.pCatID = g.FK_pCatID
left join tblNewsCategories n on n.CategoryOd = c.ConnectedNewsCatID
Try starting here:
select *,
case when PGC.pCatName = '0' then NC.CategoryName else PGC.pCatName end as [CatName]
from tblPhotoGalleries as PG inner join
tblPhotoGalleryCats as PGC on PGC.pCatID = FK_pCatID left outer join
tblNewsCategories as NC on NC.CategoryId = ConnectedNewsCatID