Showing posts with label select. Show all posts
Showing posts with label select. Show all posts

Sunday, July 15, 2018

How to return different result in the same query?

Leave a Comment

I'm trying to return different result in one query, in particular the query return the ranking of a particular competition using round.id field, now sometimes this table can have the field group.id valorized, if so I need to return only the ranking which have as group.id the minimum value available, so I create this design:

SELECT l.*, t.name as team_name, r.name AS rank_name, r.color AS rank_color FROM league_ranking l LEFT JOIN team t ON l.team_id = t.id LEFT JOIN competition_ranks r ON l.rank = r.id INNER JOIN competition_groups g  WHERE l.round_id = :round_id AND l.group_id = (   SELECT MIN(l2.group_id)   FROM league_ranking l2   WHERE l2.round_id = :round_id ) 

this working if the ranking records have the group.id available, but if this field is NULL nothing will be returned, a little example of league_ranking table data:

| round_id | group_id | team_id      5         3         1045      5         3         1046      6         NULL      1047      6         NULL      1048 

if I search as round.id 5, will be returned the first two records, but if instead I search for round.id 6, nothing will be returned. How can I structure my query to return the result also if there is no group.id associated?

1 Answers

Answers 1

null isn't a value, it's the lackthereof. null = null returns null, not true, so for groups without an id, this query won't work.

You can use the <=> instead of =, though, to evaluate two nulls as being equal:

SELECT l.*, t.name as team_name, r.name AS rank_name, r.color AS rank_color FROM league_ranking l LEFT JOIN team t ON l.team_id = t.id LEFT JOIN competition_ranks r ON l.rank = r.id INNER JOIN competition_groups g  WHERE l.round_id = :round_id AND l.group_id <=> ( -- <=> used here instead of =   SELECT MIN(l2.group_id)   FROM league_ranking l2   WHERE l2.round_id = :round_id ) 
Read More

Wednesday, January 24, 2018

What do I use instead of two multiselect boxes in html so works on Phone/Ipad

Leave a Comment

In my HTML UI I wanted users to be able to select multiple countries, because there are far too many countries to allow the complete list to be displayed I initiate the HTML page so it has two lists: The second list has just those that have been selected, the first contain all countries (except ones already selected and add to the 2nd list), the user transfer between these two lists using an Add and Remove button

I display 15 rows for each select box by setting size attribute.

<tr>     <td>         <select id="preferred_countries_all" size="15" style="width:200px" multiple="multiple">             <option value=" AF">Afghanistan</option>             <option value="AX">Åland Islands</option>             <option value="AL">Albania</option>             <option value="DZ">Algeria</option>             <option value="AS">American Samoa</option>             <option value="AD">Andorra</option>             <option value="AO">Angola</option>             <option value="AI">Anguilla</option>             <option value="AQ">Antarctica</option>             <option value="AG">Antigua and Barbuda</option>             <option value="AR">Argentina</option>             <option value="AM">Armenia</option>             <option value="AW">Aruba</option>             <option value="AU">Australia</option>             <option value="AT">Austria</option>             <option value="AZ">Azerbaijan</option>             <option value="BS">Bahamas</option>             <option value="BH">Bahrain</option>..         </select>     </td>     <td>         <button style="width:100px" type="button" id="preferred_countries_add" onclick="add_preferred_countries();">         Add         </button>         <br>         <button style="width:100px" type="button" id="preferred_countries_remove" onclick="remove_preferred_countries();">         Remove         </button>     </td>     <td>         <select id="preferred_countries_selected" name="preferred_countries_selected" size="15" style="width:200px" multiple="multiple">         </select>     </td> </tr> 

However when I view on an iPad or Phone it only displays one row so you have to click to even see what has already been selected so it no longer works. I can understand why it might do this since space is limited on these devices, and perhaps my use of two select boxes for one option is non-standard but this doesn't work for me as a UI.

What do I use instead of two multiselect boxes in HTM: so works on Android phone or iPad as well as desktop

I had an idea of having one select box that the user could select additional countries, and a disabled text field that shows what has already been selected which is updated as user selects more countries, but how would they unselect values, what is the standard way to do this ?

Edit This is what I have so far

<tr>                             <td>                                 <label title="Potential Releases from these countries get their score boosted">                                     Preferred Release Countries                                 </label>                             </td>                             <td>                                 <input disabled="disabled" name="preferredCountries" id="preferredCountries" type="text" value="" class="readonlytextinfo">                             </td>                         </tr>                         <tr>                             <td class="indentedmultiselect" colspan="2">                                 <select id="preferred_countries_select" name="preferred_countries_select" multiple="multiple" onchange="getSelectValues(preferred_countries_select, preferredCountries)">                                     <option value=" AF">Afghanistan</option><option value="ZW">Zimbabwe</option>                                 </select>                             </td>                         </tr>  <script> function getSelectValues(select, readonlylist) {   var result = [];   var options = select && select.options;   var opt;    for (var i=0, iLen=options.length; i<iLen; i++) {     opt = options[i];      if (opt.selected) {       result.push(opt.text);     }   }   readonlylist.value =result.toString();   if(readonlylist.value.length>230)   {     readonlylist.value=readonlylist.value.substring(0,230) + '...';   }   return result; } </script> 

3 Answers

Answers 1

How each solution works on mobile you have to test yourself. In the chrome dev tools (f12) you can simulate mobile but in the end nothing beats a real phone. How most mobile jquery components work is by acting on a real select item by hiding it and showing a different DOM, updating the select in the background, thereby making it compatible with forms or other code expecting a select. Some overlay the original to get the proper mobile select response but a different view.

Answers 2

What you are asking for cannot be done natively with select boxes. The Mobile browsers will do as they please. I suggest you take a good google for free good components that solve your problem instead.

Such as:

or other depending on your choice of library/framework. if you give us more information on you library stack we might guide you better.

Answers 3

You could do this with two lists of checkboxes. It's much easier to style that way, and you have pretty much the same amount of control.

Here's a basic working example: https://codepen.io/niorad/pen/wpbjLj

<ul id="list1">   <li><input type="checkbox" name="1">Item 1</li>   <li><input type="checkbox" name="2">Item 2</li>   <li><input type="checkbox" name="3">Item 3</li> </ul>  <ul id="list2">   <li><input type="checkbox" name="4">Item 4</li>   <li><input type="checkbox" name="5">Item 5</li>   <li><input type="checkbox" name="6">Item 6</li> </ul>  <button id="button">Move</button> 

const button = document.getElementById('button');  button.addEventListener('click', () => {    const list1 = document.getElementById('list1');   const list2 = document.getElementById('list2');    const checkedFrom1 = list1.querySelectorAll('input:checked');   const checkedFrom2 = list2.querySelectorAll('input:checked');    checkedFrom1.forEach(item => {     item.checked = false;     list2.appendChild(item.parentNode);   })   checkedFrom2.forEach(item => {     item.checked = false;     list1.appendChild(item.parentNode);   }) }) 
Read More

Friday, June 30, 2017

Java Hibernate org.hibernate.exception.SQLGrammarException: could not extract ResultSet on createSQLQuery

Leave a Comment

I have this method.

private final void updateAllTableFields(final Class clazz){     final String tableName = ((Table)clazz.getAnnotation(Table.class)).name();     final String sqlQuery = new StringBuilder("SET @ids = NULL; ")             .append("UPDATE ")             .append(tableName)             .append(' ')             .append("set activeRecord=:activeRecord ")             .append("where activeRecord=true and updateable=true ")             .append("and (SELECT @ids \\:= CONCAT_WS(',', id, @ids)); ")             .append("select @ids;")             .toString();     final Query query = session.createSQLQuery(sqlQuery)             .setParameter("activeRecord",Boolean.FALSE);     final Object idsList=query.uniqueResult();     System.out.println("idsList = " + idsList); }         

I want to do a update and also return the affected Ids this works Perfect using a rawSQL returns the id in a string fashion but i couldn't make it work using Hibernate any tip!!!

Thanks in advance and best regards.

UPDATE

I need to do a update and return the affected id!! I dont want to make a simple UPDATE.

you can check it out the original question here pal: https://stackoverflow.com/questions/44604763/java-hibernate-tips-about-update-all-table-fields-performance

UPDATE The error is

at org.hibernate.exception.internal.SQLExceptionTypeDelegate.convert(SQLExceptionTypeDelegate.java:80) at org.hibernate.exception.internal.StandardSQLExceptionConverter.convert(StandardSQLExceptionConverter.java:49) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:126) at org.hibernate.engine.jdbc.spi.SqlExceptionHelper.convert(SqlExceptionHelper.java:112) at org.hibernate.engine.jdbc.internal.ResultSetReturnImpl.extract(ResultSetReturnImpl.java:89) at org.hibernate.loader.Loader.getResultSet(Loader.java:2065) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1862) at org.hibernate.loader.Loader.executeQueryStatement(Loader.java:1838) at org.hibernate.loader.Loader.doQuery(Loader.java:909) at org.hibernate.loader.Loader.doQueryAndInitializeNonLazyCollections(Loader.java:354) at org.hibernate.loader.Loader.doList(Loader.java:2553) at org.hibernate.loader.Loader.doList(Loader.java:2539) at org.hibernate.loader.Loader.listIgnoreQueryCache(Loader.java:2369) at org.hibernate.loader.Loader.list(Loader.java:2364) at org.hibernate.loader.custom.CustomLoader.list(CustomLoader.java:353) at org.hibernate.internal.SessionImpl.listCustomQuery(SessionImpl.java:1873) at org.hibernate.internal.AbstractSessionImpl.list(AbstractSessionImpl.java:311) at org.hibernate.internal.SQLQueryImpl.list(SQLQueryImpl.java:141) at org.hibernate.internal.AbstractQueryImpl.uniqueResult(AbstractQueryImpl.java:966) at company.nuevemil.code.finalizarEntornoDePrueba(Test.java:56) at company.nuevemil.code.main(Test.java:27)   Caused by: com.mysql.jdbc.exceptions.jdbc4.MySQLSyntaxErrorException: You have an error in your SQL syntax; check the manual that corresponds to your MySQL server version for the right syntax to use near 'UPDATE student set activeRecord=false,uid=1 where activeRecord=true at line 1 

4 Answers

Answers 1

you have to use HQL Query for bulk update. you are going write way only thing is that, you have to create HQL query for example       Your Query Might be like this:-     final String tableName = ((Table)clazz.getAnnotation(Table.class)).name();         final String sqlQuery = new StringBuilder("SET @ids = NULL; ")                 .append("UPDATE ")                 .append(tableName)                 .append(' ')                 .append("set activeRecord=:activeRecord ")                 .append("where activeRecord=true and updateable=true ")                 .append("and (SELECT @ids \\:= CONCAT_WS(',', id, @ids)); ")                 .append("select @ids;")                 .toString();         final Query query = session.createQuery(sqlQuery)                 .setParameter("activeRecord",Boolean.FALSE);         final Object idsList=query.executeUpdate();      Example Query:     final String tableName = ((Table)clazz.getAnnotation(Table.class)).name();        Query qry = session.createQuery("update "+tableName+" p set p.proName=?     where p.productId=111");                 qry.setParameter(0,"updated..");                 int res = qry.executeUpdate(); 

Answers 2

There is no "affected id" in an UPDATE statement.

UPDATE student     set activeRecord=false,uid=1     where activeRecord=true 

may modify 0 rows, 1 rows, or many rows.

What is the PRIMARY KEY of student? Let's say it is studentId. To retrieve all (if any) of the studentId values, you neecd the Hibernate equivalent of this pseudo-code:

START TRANSACTION; @ids = SELECT studentId            FROM student            WHERE activeRecord=true  -- and updateable=true ??            FOR UPDATE; UPDATE student     SET activeRecord=false,         uid=1     WHERE activeRecord=true  -- and updateable=true ??     ; COMMIT; 

More

That code could be bundled up in a Stored Procedure, thereby allowing it to be CALLed as if a single statement. (I do not know how to make it work with Hibernate.)

Answers 3

I suppose, you won't be able to make it in Hibernate fashion.

Hibernate is independent from a database. But the part of the query that initializes a variable (I mean set @ids = null;) is not portable across all the relational databases so I wouldn't expect it to be in Hibernate API somewhere.

Answers 4

I would sugest extracting records to be updated as list of entity, then you can iterate to set values, persist and still return afected ids at the end of your method

Read More

Sunday, March 20, 2016

Adding an array of user id's to a model - Rails 4

Leave a Comment

I'm trying to make an app for students to post projects. When they create a post, they can add their team mates. Each student has a user id, and I want the student creating the project to be able to select other ids from the same organisation as their team mates. The model associations are:

user

has_and belongs_to_many :projects 

project

has_and belongs_to_many :users 

I have a project model, with:

:user_id (integer) :team_mates (integer) 

In my projects form, I want the student (creating the project, to select other ids (from a list of students who belong to the same organisation) as team mates. My first question is whether the team mates attribute should be an integer (since there might be more than one team mate, in which case, can this attribute hold an array?

My next problem is - I'm lost for how to go about this. If I add a select line to my project form, to add user_ids, where the user.organisation equals the current user's id, then the student creating the project should be able to see a list of possible options.

Then in my projects show page, I want to display each student in the team.

Can anyone help with how to approach this? I'm lost and stuck for where to find examples of similar problems.

UPDATE

I found this article: http://collectiveidea.com/blog/archives/2015/07/30/bi-directional-and-self-referential-associations-in-rails/

I'm confused though. I don't know whether I should join projects with users (through a join table I've called teams) or whether I should join users with users, through a join table called 'teams'.

If I join users with projects, it makes sense to me that the user who creates a project can choose other users to be project team mates. However, it isn't true to say that each project has many teams (which is what this example shows). I'm not sure about changing the has_many to a has_one, since the article goes on to explain about the has_many through join.

If i join users to users, then a user with many projects may have different teams for each project. So that wouldn't be correct.

Taking the article as an example, I tried:

create teams model:

class CreateTeams < ActiveRecord::Migration   def change     create_table :teams do |t|        t.references :project, index: true, foreign_key: true       t.references :team_mate, index: true         t.timestamps null: false     end     add_foreign_key :teams, :projects, column: :team_mate_id     add_index :teams, [:project_id, :team_mate_id], unique: true   end end 

Team.rb

belongs_to :project belongs_to :team_mate, class_name: "Profile" 

Teams controller (I will figure this out later - its commented for now since I don't have a matchmaker section yet):

class TeamsController < ApplicationController  before_action :resync_matches, only: :index  def index   # several orders of magnitude faster   @team_mates = current_user.team_mates                                .page(params[:page]) end  private  def resync_matches   # only resync if we have to   if current_user.teams_outdated?     new_matches = MatchMaker.matches_for(current_user)     current_user.team_mates.replace(new_matches)   end end  end 

project.rb

has_one :team has_many :team_mates, through: :teams, dependent: :destroy 

I changed this so that projects have one team rather than many.

Im confused about this and not sure how to get this up and running. In my projects form, I want to offer users (who create projects) to pick profiles of other users who are team mates. I'm lost at this point.

I tried to make a Teams Helper:

module TeamsHelper   def team_mate_options     s = ''     Profile.in_same_organisation.each do |profile|       s << "<option value='#{profile.id}'>#{profile.user.full_name}</option>"     end     s.html_safe   end    end 

In my profile.rb, I tried to make a scope to get the profiles who belong to the same organisation as the project creator (although I'm not sure this is correct):

scope :in_same_organisation, -> (organisation_id) { where(organisation_id: organisation_id) } 

Then in my projects form I tried to add a select option:

<div class="form-group">                         <%= label_tag 'team_mates', 'Choose team mates' %>                         <%= select_tag 'team_mates', team_mate_options, multiple: true, class: 'form-control chosen-it' %>                     </div> 

VISHAL'S SUGGESTION

Taking Vishal's suggestion, I have implemented the structure proposed. I'm having a problem with the projects form. My complete setup is:

Models Organisation

has_many :profiles 

Profile

  has_many :projects   belongs_to :organisation   has_many :teams, foreign_key: "team_mate_id"   has_many :team_projects, through: :teams, source: :project 

Project

belongs_to :profile has_many :teams has_many :team_mates, through: :teams 

Team

belongs_to :project belongs_to :team_mate, class_name: "Profile" 

My teams table has:

create_table "teams", force: :cascade do |t|     t.integer  "project_id"     t.integer  "team_mate_id"     t.datetime "created_at",   null: false     t.datetime "updated_at",   null: false   end 

Then in my project form, I have:

<%= f.label :team_mates, :label => "Add a team member" %> <%= f.collection_select(:team_mate_id, Profile.all, :id, :team_mate_select, {prompt: "Select the team member"}, {:required => true}) %> 

In my profile model, I have:

def team_mate_select     self.user.formal_name end 

My structure is that profiles belong to users. In user, I have method called formal name which adds a title to the users name.

When I save this and try it, I get an error that says:

undefined method `team_mate_id' for #<Project:0x007fa08ed3d8e0> 

(highlighting the collection select line of the project form)

My projects/form.html.erb has:

<%= simple_form_for(@project) do |f| %>             <%= f.error_notification %>                  <div class="form-inputs">                      <%= f.input :title, :label => "Title", autofocus: true %>                     <%= f.input :description, :as => :text, :label => "Describe your project", :input_html => {:rows => 10} %>                     <%= f.input :remark, :as => :text, :label => "Is there an interesting fact or statistic that's relevant to this research?", :input_html => {:rows => 5}, :placeholder => "In fact, ...(insert a fact which shows why this research might be interesting or relevant)" %>                      <%= f.input :hero_image, :label => "Add an image" %>                          <%= f.label :team_mates, :label => "Add a team member" %>                         <%= f.collection_select(:team_id, Profile.all, :id, :team_mate_select, {prompt: "Select the team member"}, {:required => true}) %>                   <div class="form-actions" style="margin-top:50px">                     <%= f.button :submit, "Create", :class => 'formsubmit' %>                 </div>         <% end %> 

3 Answers

Answers 1

Introduce a Team model, with has_and belongs_to_many relations between a Usermodel and a team model. Then, a Team represents an array of User objects.

Answers 2

What you are looking for is self-referential associations. You would have to create a join table that keeps the records of which user is team member of which user; something like following:

+-----------+----------------+------------+-------------+ |  user_id  | team_member_id | created_at | updated_at  | +-----------|----------------+------------+-------------+ |           |                |            |             | +-----------+----------------+------------+-------------+ 

Answers 3

You can think on the lines of 'what resource you are creating'. When you add a new project, you are creating a Project resource. When the project's creator adds someone else to the project, you are creating a ProjectMemberRelationship resource. So, I think you can get what you need with only these models - Organisation, User, Project, ProjectMemberRelationship (and a table for each of them).

You will need a projects table that has a reference to users through user_id field.

Create ProjectMemberRelationship model with

rails generate model ProjectMemberRelationship project_id:integer member_id:integer 

Organisation Model:

has_many :users 

User model:

belongs_to :organization has_many :projects has_many :project_member_relationships, foreign_key: "member_id" has_many: collaborated_projects, through: :project_member_relationships, source: :project 

You need foreign_key: "member_id" as the column name is not user_id as expected by Rails by default. And you need source: :project because the column name is not collaborated_project_id but project_id.

Project model:

belongs_to :user has_many :project_member_relationships has_many :members, through: :project_member_relationships 

ProjectMemberRelationship model:

belongs_to :project belongs_to :member, class_name: "User" 

With models defined as above, every time a member is added to a project, a new row is added to project_member_relationships table that stores the project_id for the project and member_id of the user that was added, while users & projects tables are unaffected by this action.

Let's divide the task in 2 stops.

Step 1: A user creates a project.

Step 2: The user adds collaborators to the project.

Step 1 is fairly easy and straightforward. You create a project with, say its topic and user_id of the user who created it.

Now on the project's show page, you can have a form to add a new project_member_relationship. You only need 2 fields to submit here - member_id (for the user to be added) & project_id (which equals params[:id] on projects#show page). For member_id field, you can use collection_select where your collection is the users that belong to the same organisation as the creator, as required. Mind you, one submission of this form creates only one project member at a time.

I haven't tested the code yet but I'll be happy to help if you run into issues.

Read More