I am having some trouble. I am trying to build a SQL query that uses "starts with" logic. A little background first...
In the database that I've been tasked to write reports from, there is a "user" table and a "salesperson" table, with salespersons belonging to a user. In a not-so-brilliant move, the designer of the database decided to associate the salespersons through a substring match to their employee code. For example:
John Smith's "employee_code" would be "JS". But he has multiple "salespersons" to distinguish his different sale types. So he might have "JS1", "JS2", "JS3", etc., as his "salesperson_code".
To illustrate:
user table:
|----------|-----------|----------|---------------|
| username | firstname | lastname | employee_code |
|----------|-----------|----------|---------------|
| JSMITH | John | Smith | JS |
|----------|-----------|----------|---------------|
salesperson table:
|------------------|------------------|
| salesperson_name | salesperson_code |
|------------------|------------------|
| John Smith 1 | JS1 |
| John Smith 2 | JS2 |
| John Smith 3 | JS3 |
|------------------|------------------|
There is no foreign key on the salesperson table linking them to the user table, only the substring from the employee code.
I do not remember where I found this answer, but in my queries I've been doing this:
select user.name
from user user
inner join salesperson spn on spn.salesperson_code like user.employee_code || '%'
This logic successfully does the "starts with" match. However, there are users with blank employee codes and they, also, match this query.
What I am looking for: how do I modify this query so that if the employee_code is blank it will not match? I'm pretty newbie with Oracle queries. Other DBMS' have a starts with clause that will not match blank fields.
Thank you in advance for your help!
Try this
select user.name
from user user
inner join salesperson spn
on spn.salesperson_code like nvl(trim(user.employee_code),'-') || '%'
try
select user.name
from user user
inner join salesperson spn
on spn.salesperson_code like DECODE (user.employee_code,
NULL, NULL,
user.employee_code || '%')
I would suggest using a regular expression to extract the non-digit parts of the salesperson code and optionally the digits part. Create a view for the table with these added fields or use it as a table expression in the query.
SELECT regexp_substr(salesperson_code,'\D+') AS employee_code,
regexp_substr(salesperson_code,'\d+') AS employee_sales_no,
salesperson_name, salesperson_code
FROM salesperson
Note: the regular expressions match one or more non-digits and one or more digits respectively.
Add an IS NOT NULL condition:
select *
from user
inner join salesperson spn
on spn.salesperson_code like user.employee_code || '%'
and user.employee_code is not null;
Related
I have a section table and class Table
class table is designed in this way
(id,class_name,section_id)
one class has many sections like
--------------------------------------------
| SN | ClassName | Section_id |
--------------------------------------------
| 1 | ClassOne | 1 |
| 2 | ClassOne | 2 |
| 3 | ClassOne | 3 |
| 4 | ClassOne | 4 |
--------------------------------------------
Now i want to groupBy Only ClassName and display all the sections of that class
$data['classes'] = SectionClass::groupBy('class_name')->paginate(10);
i have groupby like this but it only gives me one section id
Try this way...
$things = SectionClass::paginate(10);
$data['classes']= $things->groupBy('class_name');
You are getting just one row because that is what GROUP BY does, groups a set of rows into a set of summary rows and returns one row for each group. In standard SQL, a query that includes a GROUP BY clause cannot refer to nonaggregated columns in the select list that are not named in the GROUP BY clause. For example, in SQL Server if you try the next clause
SELECT * FROM [Class] GROUP BY [ClassName]
You'll get the next error
"Column 'SN' is invalid in the select list because it is not contained in either an aggregate function or the GROUP BY clause"
Think about it, you are grouping by ClassName, and following your sample data, this will return just one row. Your SELECT clause includes column ClassName, which is easy to get because is the same in every single row, but when you are selecting another, which one should be return if only one has to be selected?
Now, things change a little bit in MySQL. MySQL extends the standard SQL use of GROUP BY so that the select list can refer to nonaggregated columns not named in the GROUP BY clause. This means that the preceding query is legal in MySQL. However, this is useful primarily when all values in each nonaggregated column not named in the GROUP BY are the same for each group. The server is free to choose any value from each group, so unless they are the same, the values chosen are nondeterministic. You can find a complete explanation about this topic here https://dev.mysql.com/doc/refman/5.6/en/group-by-handling.html
If you are expecting a result in one row, you can use GROUP_CONCAT() function to get something like
--------------------------------
| ClassName | Sections |
--------------------------------
| ClassOne | 1,2,3,4 |
--------------------------------
Your query must be something like:
select `ClassName`, group_concat(Section_id) from `class` group by `ClassName`
You can get this with a raw query in laravel or its up to you to find a way to get the same result using query builder ;)
I need a calculated column (because this will be used in a slicer) that returns the employee's most recent supervisor.
Data sample (table 'Performance'):
EMPLOYEE | DATE | SUPERVISOR
--------------------------------------------
Jim | 2018-11-01 | Bob
Jim | 2018-11-02 | Bob
Jim | 2018-11-03 | Bill
Mike | 2018-11-01 | Steve
Mike | 2018-11-02 | Gary
Desired Output:
EMPLOYEE | DATE | SUPERVISOR | LAST SUPER
---------------------------------------------------------------
Jim | 2018-11-01 | Bob | Bill
Jim | 2018-11-02 | Bob | Bill
Jim | 2018-11-03 | Bill | Bill
Mike | 2018-11-01 | Steve | Gary
Mike | 2018-11-02 | Gary | Gary
I tried to use
LAST SUPER =
LOOKUPVALUE (
Performance[SUPERVISOR],
Performance[DATE], MAXX ( Performance, [DATE] )
)
but I get the error:
Calculation error in column 'Performance'[]: A table of multiple
values was supplied where a single value was expected.
After doing more research, it appears this approach was doomed from the start. According to this, the search value cannot refer to any column in the same table being searched. However, even when I changed the search value to TODAY() or a static date as a test, I got the same error about multiple values. MAXX() is also returning the maximum date in the entire table, not just for that employee.
I wondered if it was a many to many issue, so I went back into Power Query, duplicated the original query, grouped by EMPLOYEE to get MAX(DATE), matched both fields against the original query to get the SUPERVISOR on MAX(DATE), and can treat this like a regular lookup table. While it does work, unsurprisingly the refresh is markedly slower.
I can't decide if I'm over-complicating, over-simplifying, or just wildly off base with either approach, but I would be grateful for any suggestions.
What I'd like to know is:
Is it possible to use a simple function like LOOKUPVALUES() to achieve the desired output?
If not, is there a more efficient approach than duplicating the query?
The reason LOOKUPVALUE is giving that particular error is that it's doing a lookup on the whole table, not just the rows associated with that particular employee. So if you have multiple supervisors matching the same maximal date, then you've got a problem.
If you want to use the LOOKUPVALUE function for this, I suggest the following:
Last Super =
VAR EmployeeRows =
FILTER( Performance, Performance[Employee] = EARLIER( Performance[Employee] ) )
VAR MaxDate = MAXX( EmployeeRows, Performance[Date] )
RETURN
LOOKUPVALUE(
Performance[Supervisor],
Performance[Date], MaxDate,
Performance[Employee], Performance[Employee]
)
There are two key differences here.
I'm taking the maximal date over only the rows for that particular employee (EmployeeRows).
I'm including Employee in the lookup function, so that it
only matches for the appropriate employee.
For other possible solutions, please see this question:
Return top value ordered by another column
Multiple params received from request:
- domain
- GEO
- referer
- other params
Database table looks like that:
domain | geo | referer | utm | option_id |
---------|--------|---------|-----|-----------|
test.com | | | | 1
test.com | us | | | 2
test.com | us | ref.com | 12 | 3
test2.com| us | | | 4
For example i received some request with params:
domain=test.com
geo=us
referer=ref.com
utm=12
If i do a query:
select option_id from table where domain='test.com' and geo='us' and referer='ref.com' and utm='12';
It gives me full match result only option_id = 3
But i need to get all the options, for every match with domain and geo.
option_id = [1,2,3]
How to solve the problem in performant way, maybe the solution is not SQL database. I need to search in highload system in realtime.
Help will be useful, thank you.
The query that satisfy selection will be:
select option_id from table where domain='test.com' and geo='' and referer='' and utm=''
UNION
select option_id from table where domain='test.com' and geo='us' and referer='' and utm=''
UNION
select option_id from table where domain='test.com' and geo='us' and referer='ref.com' and utm='12'
But it is slow, i know that exist simple and performant solution. Maybe without SQL database
If you want to get all the options that match at least 1 of the params you should use OR instead of AND
select option_id from table where ( domain='test.com' OR geo='us' OR referer='ref.com' OR utm='12' );
select option_id from table where domain LIKE '%test.com%' and geo LIKE '%us%' and referer LIKE '%ref.com%' and utm like '%12%';
i'm not test this code but you must use like, it will search component with pattern.
First this is how my table looks like:
tbl
------------------------------------------
| USERID | requestID
|test1#gmail.com | sunsun#gmail.com
|sunsun#gmail.com | test1#gmail.com
|test2#gmail.com | kittyhsk#gmail.com
|sunsun#gmail.com | test2#gmail.com
|test#gmail.com | sunsun#gmail.com
|sunsun#gmail.com | test3#gmail.com
I named my columns wrong but
userIds are the ids that are following requestIds,
and requestIds are the ids that are being followed.
What I want to do is to find the cases that the ids are following each other.
Like for example, I log in with the id sunsun#gmail.com(this is not real address), then I find ids that I'm following and also the ids that follows me, but under the ids that are following each other, I want to print out some text saying that they are following each other. (So under test1 and test2, I should have that text.)
I found this but this does not really apply to my situation as I have to get the results under one logged in ID.
I was trying to do this by myself but I'm all out of ideas. Please help me out. Thanks in advance.
You will have to join the table with itself and compare. So something like
SELECT *
FROM table as t1
JOIN table as t2
ON t1.requestid = t2.useriD and t1.userid = t2.requestid
I have the following table called questions in HQL Hibernate:
ID | Name
1 | Bread
2 | Bread
3 | Rise
4 | Rise
I want to select each PRODUT only once and if there are multiple PRODUCT with the same name, select the one of the highest id. So, the expected results:
ID | NAME
3 | Bread
4 | Rise
I use the following query:
from Product AS E group by E.producto
So it selects the first 'Product' it encounters instead of the last one.
Thanks
The syntax is almost identical to SQL:
select max(p.id), p.name from Product p group by p.name
Relevant documentation:
http://docs.jboss.org/hibernate/core/4.3/manual/en-US/html/ch16.html#queryhql-aggregation
http://docs.jboss.org/hibernate/core/4.3/manual/en-US/html/ch16.html#queryhql-grouping